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

最近闲来无事,开始摸索前端单元测试。一是不备之需,二是确实在实际项目中能够用到单元测试。这样可以提高开发效率,提升代码质量,完全可以单独对 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

时间: 2024-09-18 09:53:16

来,加入前端自动化单元测试的相关文章

前端开发自动化单元测试趋势

时至今日,Web 前端已经发生了巨大的演变,而单页应用程序也成为了标准.众多应用程序完成了从 PC 到移动端的华丽转身,而那些基于 JavaScript 的框架变得更受开发者们欢迎. TestProject 进行了一项调查,以便了解目前前端开发技术和自动化单元测试的趋势.调查的结果揭示了软件专业人士对热门框架,以及工具的偏好程度.我们从 957 个相关人士的调查问卷中,得出了这个让人印象深刻的结果! 调查方式 向 2,735 名相关者发出在线问卷调查,其中 957 人回答了问卷中的问题. 数据收

Grunt安装配置教程:前端自动化工作流

文章简介:Grunt 打造前端自动化工作流. Grunt这货是啥? 最近很火的前端自动化小工具,基于任务的命令行构建工具 http://gruntjs.com Grunt能帮我们干啥? 在开始介绍前,先向大家描述下面的场景: [场景1:项目开始前] 先建立一个 projA 的文件夹 再建 html css js images (建5个或以上文件夹,花费1分钟) 拷贝 CSS库(Yui Reset bootstrap)JS库(Requiet.js Seajs jQuery jQuery插件 ) 进

自动化单元测试的实践之路

自动化单元测试并不是什么新鲜事物,它应该是团队持之以恒的事情,可能有很多团队知道如何去做,但是还做得不够好:还有不少团队不知道如何去做,甚至有一些旧系统还不敢去重构,还在坚持着Java中的main方法调用的方式来执行,在漫长等待构建结果. 本文主要讲基于Java项目如何做自动化单元测试的实践. 1 是否值得 关于单元测试的意义,详细参考stackoverflow这篇文章: http://stackoverflow.com/questions/67299/is-unit-testing-worth

Web前端自动化入门总结

周末失眠,周一无力写代码,只能听着一首:逆流成河,顺便把最近刚入门的前端自动化写一下入门总结. 因为从事的开发重点是java后端,后端这几年随着maven,gradle等构建工具的使用也把以前jar管理解放了,记得刚毕业那会公司的方案是公司自己维护一个libs文件夹,把需要的jar放进去,然后ant写脚本打包.这种方式的缺点要自己记住jar的版本等等,然后更新比较繁琐,还有把jar提交到svn等版本管理工具,大小很大,共享麻烦. 说到前端自动化,现在应该是比较普及了,到github上面搜索一下w

自动化单元测试实践之路

自动化单元测试并不是什么新鲜事物,它应该是团队持之以恒的事情,可能有很多团队知道如何去做,但是还做得不够好:还有不少团队不知道如何去做,甚至有一些旧系统还不敢去重构,还在坚持着Java中的main方法调用的方式来执行,在漫长等待构建结果. 本文主要讲基于Java项目如何做自动化单元测试的实践. 1 是否值得 关于单元测试的意义,详细参考stackoverflow这篇文章: http://stackoverflow.com/questions/67299/is-unit-testing-worth

Karma和Jasmine自动化单元测试

前言 在Java领域,Apache, Spring, JBoss 三大社区的开源库,包罗万象,但每个库都在其领域中都鹤立鸡群.而Nodejs中各种各样的开源库,却让人眼花缭乱,不知从何下手. Nodejs领域: Jasmine做单元测试,Karma自动化完成单元测试,Grunt启动Karma统一项目管理,Yeoman最后封装成一个项目原型模板,npm做nodejs的包依赖管理,bower做javascript的包依赖管理.Java领域:JUnit做单元测试, Maven自动化单元测试,统一项目管

Gulp构建前端自动化工作流

## Gulp构建前端自动化工作流 ### Gulp构建前端自动化工作流之:常用插件介绍及使用 在对Gulp有了一个初步的了解之后,我们开始构建一个较为完整的Gulp开发环境. 本文主要分为6个段落: * 1\. 构建项目目录结构(Directory Structure Build)* 2\. 插件介绍及使用方法(Tasks and dependencies)* 3\. 扩展优化(Extend & Optimize Task)* 4\. 其他插件介绍(Other plug-ins)* 5\. 匹

详解前端自动化工具gulp自动添加版本号_javascript技巧

之前,我介绍了学习安装并配置前端自动化工具Gulp,觉得gulp确实比grunt的配置简单很多,于是我决定再深入学习一下gulp,就去网上查了资料,发现gulp还可以自动添加版本号,这个功能就为我平时在更新css或js时老是在客户端存在缓存导致更新后的效果无法实时展现的苦恼.所以就赶紧去试了一下,果真可以,很高兴啊,真是为项目开发,为效果的快速展现提供了很多的便利. 实现原理: 1.修改js和css文件: 2.通过对js,css文件内容进行hash运算,生成一个文件的唯一hash字符串(如果文件

《测试驱动的嵌入式C语言开发》——2.3节CppUTest:一个用C++实现的自动化单元测试框架

2.3 CppUTest:一个用C++实现的自动化单元测试框架现在你已经见过了Unity,接下来我会快速介绍一下CppUTest,同时也是我更倾向于使用的对C和C++代码进行单元测试的自动化测试框架.事实上,不仅因为它是一个功能全面的测试框架,同时也因为我是CppUTest的作者之一.本书开始的几个例子会用Unity,在第8章之后会使用CppUTest.CppUTest是为了支持在多种操作系统上开发嵌入式软件而特别设计的.CppUTest的宏被设计成不需要了解C++也可以写测试用例.这使得C程序