为什么要测试
首先,我们要清楚为什么要测试。说白了就是检验我们写的代码是否有错误或者是需要优化的地方,从而提高我们的代码质量。要有自动化测试就需要写测试用例,在发布之前跑一遍测试用例,可以保证测试用例覆盖的地方是没有bug。
自动化测试另一个好处就是效率高,比如一个按钮的功能交给测试人员去测,需要找到页面点击对应按钮然后根据才能知道这个功能是否有问题。那交给机器,通过脚本去跑程序来判断是否正确要更快更准确,而且每次改动代码之后可以马上接入自动化测试检查是否有错误。总之,机器测试的效率肯定是要去人测试快多啦。每一次需求迭代更新,代码修改后,回归测试。
测试工具
测试框架:
Mocha、Jasmine等等,主要是提供了清晰简明的语法来描述测试用例,测试分组以及测试不通过报错,具体哪报的错,什么原因报错等等。测试框架通常提供BDD(行为驱动开发)和TDD(测试驱动开发)两种测试语法来编写测试用例。Mocha支持两种,而Jasmine只支持BDD,下面会以Mocha的BDD为例。断言库:
Should.js、chai、expect.js等等,断言库提供了多少语义化的方法提供各种情况的判断。当然也不可以不用断言库,nodejs本来也有assert断言模块,下面会以Should.js为例。代码覆盖率:
Istanbul是本地测试代码覆盖率常用的工具之一,它提供了一系列代码覆盖率的测试指标,可以清晰的知道哪方面的代码没有覆盖到。
TDD
TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码
BDD
行为驱动开发(Behavior-Driven Development)(简写BDD),在软件工程中,BDD是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。
参考:TDD & BDD
简单nodejs项目例子
目录结构
.├── node_modules└── src└── index.js└── test└── test.js├── package.json└── README.md
1.首先需要安装测试框架和断言库:
npm install mocha should --save-dev
2.测试用例:
'use strict'require('should');const factorial = require('../src/index');describe('test index', function (){before(function(){// Stuff to do before the tests, like imports, what not});describe('#factorial()', function (){it('should return 1 when given 0', function (){factorial(0).should.equal(1);});it('should return 1 when given 1', function (){factorial(1).should.equal(1);});it('should return 2 when given 2', function (){factorial(2).should.equal(2);});it('should return 6 when given 3', function (){factorial(3).should.equal(6);});});after(function () {// Anything after the tests have finished});});
it()
it()函数定义了一个测试用例,通过Should.js提供的api,可以非常语义化的描述测试用例describe: 给测试用例分组
为了尽可能多的覆盖各种情况,测试用例往往会有很多。这时候通过分组就可以比较方便的管理(这里提一句,describe是可以嵌套的,也就是说外层分组了之后,内部还可以分子组)。另外还有一个非常重要的特性,就是每个分组都可以进行预处理(before、beforeEach)和后处理(after, afterEach)。
3.实现代码:
'use strict'const factorial = function (n) {if (n < 0) return NaN;if (n === 0) return 1;return n * factorial(n - 1);};module.exports = factorial
4.在package.json文件中加入命令
"scripts": {"test": "mocha"},
5.run test
npm run test
异步代码的例子
1.测试用例
'use strict';require('should');const mylib = require('../src/promise');describe('test promise', () => {it('Welcome to Tmall', () => {return mylib('Tmall').should.be.fulfilledWith('Hello Tmall');});});
Should.js在8.x.x版本自带了Promise支持,可以直接使用fullfilled()、rejected()、fullfilledWith()、rejectedWith()等等一系列API测试Promise对象。
2.promise实现代码
'use strict';module.exports = name => new Promise(resolve => setTimeout(() => {resolve(`Hello ${name}`)}, 2000));
默认超时时间是2000ms, 可以通过
mocha --timeout 4000修改
代码覆盖率
1.安装istanbul
npm install istanbul --save-dev
当使用istanbul运行Mocha时,istanbul命令自己的参数放在—之前,需要传递给Mocha的参数放在—之后
2.修改script命令
"scripts": {"cover": "istanbul cover mocha -- --delay"},
windows下 mocha 换成 node_modules/mocha/bin/_mocha ,否则会找不到
3.覆盖率报告
=============================== Coverage summary ===============================Statements : 92.86% ( 13/14 )Branches : 83.33% ( 5/6 )Functions : 100% ( 4/4 )Lines : 88.89% ( 8/9 )================================================================================语句覆盖率(statement coverage):是否每个语句都执行了?分支覆盖率(branch coverage):是否每个if代码块都执行了?函数覆盖率(function coverage):是否每个函数都调用了?行覆盖率(line coverage):是否每一行都执行了?
接入karma
A simple tool that allows you to execute JavaScript code in multiple real browsers.
1.加载依赖包
"babel": "^6.23.0","babel-core": "^6.26.3","babel-loader": "^7.1.5","istanbul": "^0.4.5","karma": "^4.2.0","karma-chrome-launcher": "^3.0.0","karma-coverage": "^1.1.2","karma-firefox-launcher": "^1.1.0","karma-mocha": "^1.3.0","karma-phantomjs-launcher": "^1.0.4","karma-should": "^1.0.0","karma-spec-reporter": "0.0.32","karma-webpack": "^4.0.2","mocha": "^6.1.4","phantomjs-prebuilt": "^2.1.16","should": "^13.2.3","webpack": "^4.35.3"
2.配置文件
'use strict';module.exports = function(config) {config.set({frameworks: ['mocha'],files: ['./node_modules/should/should.js','src/**/*.js','test/**/*.js'],preprocessors: {'src/**/*.js': ["webpack", 'coverage'],'test/**/*.js': ["webpack", 'coverage']},plugins: ["karma-webpack", 'karma-should', 'karma-mocha', 'karma-phantomjs-launcher', 'karma-chrome-launcher', 'karma-firefox-launcher', 'karma-coverage', 'karma-spec-reporter'],webpack: {module: {rules: [{test: /\.js$/,exclude: /(node_modules|bower_components)/,use: [{loader: 'babel-loader'},]},]}},browsers: ['PhantomJS', 'Firefox', 'Chrome'],reporters: ['spec', 'coverage'],coverageReporter: {dir: 'coverage',reporters: [{type: 'json',subdir: '.',file: 'coverage.json',}, {type: 'lcov',subdir: '.'}, {type: 'text-summary'}]}});};