来,加入前端自动化单元测试

简介:


最近闲来无事,开始摸索前端单元测试。一是不备之需,二是确实在实际项目中能够用到单元测试。这样可以提高开发效率,提升代码质量,完全可以单独对 JS 进行测试,无需页面,不依赖其他第三方。

为什么需要单元测试

在这里首先需要知道单元测试的目的及结果:

  • 使代码健壮,质量高,兼容各种临界点;
  • 减少 QA 测试报告的反馈,提高自我影响力;
  • 保证代码的整洁清晰。

如果需要刨根问底追究为什么需要进行单元测试,那我们可以开始讲讲实际项目开发中遇到的一些问题:

  • QA 不断反馈代码有 BUG (此时你正在投入的开发,然后被打扰...);
  • 代码出现 BUG,叠加代码修复 BUG(代码越来越难维护...);
  • 已经开发完成一个模块,但是没有页面提供调试测试;
  • 你开发完成的功能,每次都有许多细小的 BUG(个人影响力下降...)。

好了,列举了这么多原因,相信你也开始心虚了,回去继续搬砖检查检查代码有没有问题,如果你面色从容,大神,请手下我的膝盖。

总结:单元测试的目的只有一个,用来确定是否适合使用

如何进行单元测试

如果明白了为什么要进行单元测试,相信你已经可以开始着手为自己的代码写一些单元测试代码。测试从字面理解就是检验,看对象是否达标,达标就是 pass,不达标就是 fail。产品有这样一个需求,如果结果是 3 达到目标且返回的为有效的数字类型才可以进行比较,下面看个栗子:

 
  1. /** 
  2.  * 获取 a 除以 b 的结果 
  3.  * @param  {[Number]} a [数字] 
  4.  * @param  {[Number]} b [数字] 
  5.  * @return {[Number]}   [结果数字] 
  6.  */ 
  7. function division(a, b) { 
  8.     return a / b; 
  9.  
  10. // 测试代码 
  11. function test() { 
  12.     var result = division(6, 2); 
  13.      
  14.     if (result === 3) { 
  15.         console.log('pass'); 
  16.     } else { 
  17.         console.log('fail'); 
  18.     } 
  19. }  

咋一看上面的代码没什么问题,可以满足产品的需求,但是问题来了,如果 b 为 0,这个模块就出现了 BUG,同时如果下次需要达到其他的值就算通过,那就得去修改测试代码,这样的测试代码本身也太不健全。于是乎有了下面的方式:

 
  1. /** 
  2.  * 获取 a 除以 b 的结果 
  3.  * @param  {[Number]} a [数字] 
  4.  * @param  {[Number]} b [数字] 
  5.  * @return {[Number]}   [结果数字] 
  6.  */ 
  7. function division(a, b) { 
  8.  
  9.     if (b === 0) { 
  10.         return 0; 
  11.     } else { 
  12.         return a / b; 
  13.     } 
  14.  
  15. function test(name, result, expect) { 
  16.  
  17.     if (result === expect) { 
  18.         console.log(name + '-> pass'); 
  19.     } else { 
  20.         console.log(name + '-> fail'); 
  21.     } 
  22. test('normal number', division(6, 2), 3); 
  23. test('zero', division(6, 0), 0);  

如果需要期望值为 10 就通过,那可以这样:

 
  1. test('normal number is 10', division(20, 2), 10); 

单元测试环境搭建及代码示例

但是随着前端迅速的发展,也出现了很多测试框架,下面我演示我在实际项目中使用的测试框架环境配置 karma + jasmine,对于 karma、jasmine 我就不介绍,网上一搜一大把介绍:

1. 安装 node 环境

依赖于 node 作为基础环境,安装完成在控制台运行下面命令查看是否安装成功。

 
  1. node -v 

2. 新建目录并通过以下命令初始化项目配置 package.json

 
  1. npm init 

在 package.json scripts: {} 添加以下内容:

 
  1. "test""karma start karma.conf.js" 

3. 依次安装测试框架

 
  1. npm install karma -g 
  2. npm install jasmine --save-dev 
  3. npm install karma-jasmine --save-dev 
  4. npm install karma-chrome-launcher --save-dev 
  5. npm install jasmine-core --save-dev  

或者一次性安装

 
  1. npm install karma -g 
  2.  
  3. npm install jasmine karma-jasmine karma-chrome-launcher jasmine-core --save-dev  

运行以下命令新建 karma.conf.js(根目录下不是必须)

 
  1. karma init 

文件内容及说明:

 
  1. /** 
  2.  * karma 自动化测试参数配置 
  3.  */ 
  4.  
  5. module.exports = function(config) { 
  6.     config.set({ 
  7.  
  8.         // 基础路径,用在files,exclude属性上 
  9.         basePath: ''
  10.  
  11.         // 可用的测试框架: https://npmjs.org/browse/keyword/karma-adapter 
  12.         frameworks: ['jasmine'], 
  13.  
  14.         // 需要加载到浏览器的文件列表 
  15.         files: [ 
  16.             './src/**/*.js'
  17.             './test/unit/specs/*.spec.js' 
  18.         ], 
  19.  
  20.         // 排除的文件列表 
  21.         exclude: [ 
  22.             'karma.conf.js' 
  23.         ], 
  24.  
  25.         // 在浏览器使用之前处理匹配的文件 
  26.         // 可用的预处理: https://npmjs.org/browse/keyword/karma-preprocessor 
  27.         preprocessors: {}, 
  28.  
  29.         // 使用测试结果报告者 
  30.         // 可能的值: "dots""progress" 
  31.         // 可用的报告者: https://npmjs.org/browse/keyword/karma-reporter 
  32.         reporters: ['progress'], 
  33.  
  34.         // web server port 
  35.         port: 9876, 
  36.  
  37.         // 启用或禁用输出报告或者日志中的颜色 
  38.         colors: true
  39.  
  40.         /** 
  41.          * 日志等级 
  42.          * 可能的值: 
  43.          * config.LOG_DISABLE //不输出信息 
  44.          * config.LOG_ERROR    //只输出错误信息 
  45.          * config.LOG_WARN //只输出警告信息 
  46.          * config.LOG_INFO //输出全部信息 
  47.          * config.LOG_DEBUG //输出调试信息 
  48.          */ 
  49.         // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 
  50.         logLevel: config.LOG_INFO, 
  51.  
  52.         // 启用或禁用自动检测文件变化进行测试 
  53.         autoWatch: true
  54.  
  55.         // 测试启动的浏览器 
  56.         // 可用的浏览器: https://npmjs.org/browse/keyword/karma-launcher 
  57.         browsers: ['Chrome'], 
  58.  
  59.         // 开启或禁用持续集成模式 
  60.         // 设置为true, Karma将打开浏览器,执行测试并最后退出 
  61.         singleRun: false
  62.  
  63.         // 并发级别(启动的浏览器数) 
  64.         concurrency: Infinity, 
  65.  
  66.         // 依赖插件 
  67.         plugins: [ 
  68.             'karma-chrome-launcher'
  69.             'karma-jasmine' 
  70.         ] 
  71.     }) 
  72. }  

5. 新建源代码及测试代码目录,目录结构如下:

 
  1. project 
  2.     - node_modules 
  3.         - *(node 模块) 
  4.     - src 
  5.         - FQA 
  6.             - index.js 
  7.     - test 
  8.         - unit 
  9.             - specs 
  10.                 - *.spec.js 
  11.     - karma.conf.js 
  12.     - package.json  

6. 测试代码

。index.js 源码

 
  1. /** 
  2.  - test map method callback and parseInt param use 
  3.  - @return {[Array]} [Array] 
  4.  */ 
  5. function checkMap() { 
  6.     var nums = ['1''2''3']; 
  7.  
  8.     return nums.map(parseInt); 
  9.  
  10. /** 
  11.  - test null is Object,and common object is same 
  12.  - @return {[Array]} [Array] 
  13.  */ 
  14. function typeofAndInstanceOf() { 
  15.     var result = []; 
  16.     result.push(typeof null); 
  17.     result.push(null instanceof Object); 
  18.  
  19.     return result; 
  20.  
  21. /** 
  22.  - 检测操作符优先级 
  23.  - @return {[string]} [返回字符串] 
  24.  */ 
  25. function checkOperators() { 
  26.     var result = 'autoTest'
  27.     result = 'Value is ' + (result === 'autoTest') ? 'Something' : 'Nothing'
  28.  
  29.     return result; 
  30. }  

。fqa.spec.js 测试代码

 
  1. /** 
  2.  - test index.js checkMap method 
  3.  - detail: 
  4.  -     parseInt(val, base), base is 2 ~ 36, otherwise value equal NaN. 
  5.  */ 
  6. describe('test map and callback parseInt'function() { 
  7.      
  8.     it('a array call map'function() { 
  9.         var nums = checkMap(); 
  10.         console.log(nums); 
  11.  
  12.         expect([1, NaN, NaN]).toEqual(nums); 
  13.     }); 
  14. }); 
  15.  
  16. /** 
  17.  - test index.js typeofAndInstanceOf method 
  18.  - detail: 
  19.  -     typeof null qeual 'object', but null instanceof Object equal false, because null Constructor not Object. 
  20.  */ 
  21. describe('test null is object'function() { 
  22.      
  23.     it('null object'function() { 
  24.         var result = typeofAndInstanceOf(); 
  25.         console.log(result); 
  26.  
  27.         expect(['object'false]).toEqual(result); 
  28.     }); 
  29. }); 
  30.  
  31. /** 
  32.  - test index.js checkOperators method 
  33.  - detail: 
  34.  -     compare operator precedence, + gt ?. 
  35.  */ 
  36. describe('test null is object'function() { 
  37.  
  38.     it('test operator preceence'function() { 
  39.         var result = checkOperators(); 
  40.         console.log(result); 
  41.  
  42.         expect('Something').toEqual(result); 
  43.     }); 
  44. });  

7. 运行 sudo npm run test 执行测试代码

 
  1. "scripts": { 
  2.     "test""karma start karma.conf.js" 
  3. }  

结果:

解答

1. npm run test 运行的实际上是 package.json 中配置的命令:

 
  1. "test""karma start karma.conf.js" 

2. describe 定义测试模块,it 测试一个单元,describe 内部可以同时定义多个 it,因此可以做一系列的单元测试,测试方法详见官方文档。

3. karma.conf.js 配置 files 设置测试时需要被加载的文件

 
  1. files: [ 
  2.     './src/**/*.js'
  3.     './test/unit/specs/*.spec.js' 

总结

希望看完这篇文章,你也能够动起手来,开始编写一些单元测试代码,提高代码的质量,提升自己的周围影响力。本篇文章内容表述了实际项目开发中会遇到的问题,我们可以通过单元测试来减少这类问题的发生,以提高代码的安全性,代码的质量,从而保证产品的稳定性。点击此处查看更多文章。


作者:佚名

来源:51CTO

相关文章
|
3月前
|
资源调度 测试技术 Linux
一款接口自动化神器—开源接口测试平台Lim(Less is More)
一款接口自动化神器—开源接口测试平台Lim(Less is More)
133 2
|
3月前
|
安全 测试技术 持续交付
接口自动化测试的基本流程
接口自动化测试的基本流程
|
4月前
|
敏捷开发 存储 测试技术
敏捷测试中的挑战和自动化风险
敏捷测试中的挑战和自动化风险
|
3天前
|
缓存 监控 前端开发
【Flutter前端技术开发专栏】Flutter应用的性能调优与测试
【4月更文挑战第30天】本文探讨了Flutter应用的性能调优策略和测试方法。性能调优对提升用户体验、降低能耗和增强稳定性至关重要。优化布局(避免复杂嵌套,使用`const`构造函数)、管理内存、优化动画、实现懒加载和按需加载,以及利用Flutter的性能工具(如DevTools)都是有效的调优手段。性能测试包括基准测试、性能分析、压力测试和电池效率测试。文中还以ListView为例,展示了如何实践这些优化技巧。持续的性能调优是提升Flutter应用质量的关键。
【Flutter前端技术开发专栏】Flutter应用的性能调优与测试
|
3天前
|
前端开发 测试技术 持续交付
【Flutter 前端技术开发专栏】Flutter 中的 UI 测试与自动化测试
【4月更文挑战第30天】本文探讨了 Flutter 应用中UI测试和自动化测试的重要性,包括保障质量、提高效率和增强开发信心。Flutter提供`flutter_test`库进行Widget测试,以及`flutter_driver`进行集成测试。UI测试涵盖界面布局、交互和状态变化的验证,最佳实践建议尽早引入测试、保持用例简洁,并结合手动测试。未来,随着Flutter技术发展,UI测试和自动化测试将更加完善,助力开发高质量应用。
【Flutter 前端技术开发专栏】Flutter 中的 UI 测试与自动化测试
|
4天前
|
机器学习/深度学习 人工智能 算法
深入分析自动化测试中AI驱动的测试用例生成技术
【4月更文挑战第29天】随着人工智能技术的不断发展,其在软件测试领域的应用也越来越广泛。本文主要探讨了AI驱动的测试用例生成技术在自动化测试中的应用,以及其对提高测试效率和质量的影响。通过对现有技术的深入分析和实例演示,我们展示了AI如何通过学习和理解软件行为来自动生成有效的测试用例,从而减少人工编写测试用例的工作量,提高测试覆盖率,降低错误检测的成本。
|
6天前
|
IDE 测试技术 持续交付
【专栏】Python自动化测试与单元测试框架:提升代码质量与效率
【4月更文挑战第27天】本文探讨了Python自动化测试与单元测试框架在提升代码质量与效率中的作用。Selenium、Appium用于Web和移动应用自动化测试,pytest提供强大、易扩展的测试支持。unittest是Python标准的单元测试框架,支持结构化测试用例和丰富的断言。实践中,应制定测试计划,编写高质量测试用例,实行持续集成与测试,并充分利用测试报告。这些工具和策略能有效保障代码质量和提升开发效率。
|
6天前
|
测试技术 API 持续交付
【专栏】Python自动化测试与单元测试框架
【4月更文挑战第27天】本文探讨了Python在自动化测试与单元测试中的应用,强调其简洁语法和丰富库的优势。文章分为三部分:首先,阐述自动化测试的重要性及Python的易学性、库支持、跨平台和社区支持;其次,介绍了Python的Unittest标准测试框架和Pytest第三方框架的特点与用法;最后,讨论了Web UI和API自动化测试实践,并提出持续集成、测试金字塔等最佳实践。Python为软件开发的测试环节提供了强大支持,帮助构建更稳定的系统。
|
7天前
|
安全 Java 测试技术
Spring Boot 自动化单元测试类的编写过程
企业开发不仅要保障业务层与数据层的功能安全有效,也要保障表现层的功能正常。但是我们一般对表现层的测试都是通过postman手工测试的,并没有在打包过程中代码体现表现层功能被测试通过。那么能否在测试用例中对表现层进行功能测试呢?答案是可以的,我们可以使用MockMvc来实现它。
27 0
|
9天前
|
测试技术 API 网络架构
Python的api自动化测试 编写测试用例
【4月更文挑战第18天】使用Python进行API自动化测试,可以结合`requests`库发送HTTP请求和`unittest`(或`pytest`)编写测试用例。以下示例: 1. 安装必要库:`pip install requests unittest` 2. 创建`test_api.py`,导入库,定义基础URL。 3. 创建继承自`unittest.TestCase`的测试类,包含`setUp`和`tearDown`方法。 4. 编写测试用例,如`test_get_users`,检查响应状态码和内容。 5. 运行测试:`python -m unittest test_api.py`
14 2