最近闲来无事,开始摸索前端单元测试。一是不备之需,二是确实在实际项目中能够用到单元测试。这样可以提高开发效率,提升代码质量,完全可以单独对 JS 进行测试,无需页面,不依赖其他第三方。
为什么需要单元测试
在这里首先需要知道单元测试的目的及结果:
- 使代码健壮,质量高,兼容各种临界点;
- 减少 QA 测试报告的反馈,提高自我影响力;
- 保证代码的整洁清晰。
如果需要刨根问底追究为什么需要进行单元测试,那我们可以开始讲讲实际项目开发中遇到的一些问题:
- QA 不断反馈代码有 BUG (此时你正在投入的开发,然后被打扰…);
- 代码出现 BUG,叠加代码修复 BUG(代码越来越难维护…);
- 已经开发完成一个模块,但是没有页面提供调试测试;
- 你开发完成的功能,每次都有许多细小的 BUG(个人影响力下降…)。
好了,列举了这么多原因,相信你也开始心虚了,回去继续搬砖检查检查代码有没有问题,如果你面色从容,大神,请手下我的膝盖。
总结:单元测试的目的只有一个,用来确定是否适合使用
如何进行单元测试
如果明白了为什么要进行单元测试,相信你已经可以开始着手为自己的代码写一些单元测试代码。测试从字面理解就是检验,看对象是否达标,达标就是 pass,不达标就是 fail。产品有这样一个需求,如果结果是 3 达到目标且返回的为有效的数字类型才可以进行比较,下面看个栗子:
咋一看上面的代码没什么问题,可以满足产品的需求,但是问题来了,如果 b 为 0,这个模块就出现了 BUG,同时如果下次需要达到其他的值就算通过,那就得去修改测试代码,这样的测试代码本身也太不健全。于是乎有了下面的方式:
如果需要期望值为 10 就通过,那可以这样:
单元测试环境搭建及代码示例
但是随着前端迅速的发展,也出现了很多测试框架,下面我演示我在实际项目中使用的测试框架环境配置 karma + jasmine,对于 karma、jasmine 我就不介绍,网上一搜一大把介绍:
安装 node 环境
依赖于 node 作为基础环境,安装完成在控制台运行下面命令查看是否安装成功。1node -v新建目录并通过以下命令初始化项目配置 package.json
1npm init在 package.json scripts: {} 添加以下内容:
1"test": "karma start karma.conf.js"依次安装测试框架
12345npm install karma -gnpm install jasmine --save-devnpm install karma-jasmine --save-devnpm install karma-chrome-launcher --save-devnpm install jasmine-core --save-dev或者一次性安装
12npm install karma -gnpm install jasmine karma-jasmine karma-chrome-launcher jasmine-core --save-dev运行以下命令新建 karma.conf.js(根目录下不是必须)
1karma init文件内容及说明:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172/*** karma 自动化测试参数配置*/module.exports = function(config) {config.set({// 基础路径,用在files,exclude属性上basePath: '',// 可用的测试框架: https://npmjs.org/browse/keyword/karma-adapterframeworks: ['jasmine'],// 需要加载到浏览器的文件列表files: ['./src/**/*.js','./test/unit/specs/*.spec.js'],// 排除的文件列表exclude: ['karma.conf.js'],// 在浏览器使用之前处理匹配的文件// 可用的预处理: https://npmjs.org/browse/keyword/karma-preprocessorpreprocessors: {},// 使用测试结果报告者// 可能的值: "dots", "progress"// 可用的报告者: https://npmjs.org/browse/keyword/karma-reporterreporters: ['progress'],// web server portport: 9876,// 启用或禁用输出报告或者日志中的颜色colors: true,/*** 日志等级* 可能的值:* config.LOG_DISABLE //不输出信息* config.LOG_ERROR //只输出错误信息* config.LOG_WARN //只输出警告信息* config.LOG_INFO //输出全部信息* config.LOG_DEBUG //输出调试信息*/// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUGlogLevel: config.LOG_INFO,// 启用或禁用自动检测文件变化进行测试autoWatch: true,// 测试启动的浏览器// 可用的浏览器: https://npmjs.org/browse/keyword/karma-launcherbrowsers: ['Chrome'],// 开启或禁用持续集成模式// 设置为true, Karma将打开浏览器,执行测试并最后退出singleRun: false,// 并发级别(启动的浏览器数)concurrency: Infinity,// 依赖插件plugins: ['karma-chrome-launcher','karma-jasmine']})}新建源代码及测试代码目录,目录结构如下:
123456789101112project- node_modules- *(node 模块)- src- FQA- index.js- test- unit- specs- *.spec.js- karma.conf.js- package.json测试代码
index.js 源码
1234567891011121314151617181920212223242526272829303132/**- test map method callback and parseInt param use- @return {[Array]} [Array]*/function checkMap() {var nums = ['1', '2', '3'];return nums.map(parseInt);}/**- test null is Object,and common object is same- @return {[Array]} [Array]*/function typeofAndInstanceOf() {var result = [];result.push(typeof null);result.push(null instanceof Object);return result;}/**- 检测操作符优先级- @return {[string]} [返回字符串]*/function checkOperators() {var result = 'autoTest';result = 'Value is ' + (result === 'autoTest') ? 'Something' : 'Nothing';return result;}fqa.spec.js 测试代码
1234567891011121314151617181920212223242526272829303132333435363738394041424344/**- test index.js checkMap method- detail:- parseInt(val, base), base is 2 ~ 36, otherwise value equal NaN.*/describe('test map and callback parseInt', function() {it('a array call map', function() {var nums = checkMap();console.log(nums);expect([1, NaN, NaN]).toEqual(nums);});});/**- test index.js typeofAndInstanceOf method- detail:- typeof null qeual 'object', but null instanceof Object equal false, because null Constructor not Object.*/describe('test null is object', function() {it('null object', function() {var result = typeofAndInstanceOf();console.log(result);expect(['object', false]).toEqual(result);});});/**- test index.js checkOperators method- detail:- compare operator precedence, + gt ?.*/describe('test null is object', function() {it('test operator preceence', function() {var result = checkOperators();console.log(result);expect('Something').toEqual(result);});});
运行 sudo npm run test 执行测试代码
123"scripts": {"test": "karma start karma.conf.js"}结果:
解答
npm run test 运行的实际上是 package.json 中配置的命令:
1"test": "karma start karma.conf.js"describe 定义测试模块,it 测试一个单元,describe 内部可以同时定义多个 it,因此可以做一系列的单元测试,测试方法详见官方文档。
- karma.conf.js 配置 files 设置测试时需要被加载的文件1234files: ['./src/**/*.js','./test/unit/specs/*.spec.js']
总结
希望看完这篇文章,你也能够动起手来,开始编写一些单元测试代码,提高代码的质量,提升自己的周围影响力。本篇文章内容表述了实际项目开发中会遇到的问题,我们可以通过单元测试来减少这类问题的发生,以提高代码的安全性,代码的质量,从而保证产品的稳定性。