单元测试就是测试最小单元(一个方法,一个组件)。git
虽然你们都已经回答过无数次这个问题了,可是那并不表明我确实理解了。github
我之前也没有写过单元测试,这也是为何要来记录这篇文章的缘由。npm
对于写单元测试,我我的的直观感触是能够促使本身编写更“纯”的函数或方法。这其实对于代码的阅读、维护、重构等都带来了优惠。你能够更加明确这个函数的做用,至少会千方百计让本身的函数所影响的范围进行缩减、可控。json
再者说,对于 CI/CD,单元测试又是很是有必要的一个环节。bash
我也相应的搜索了一些网络上小伙伴们的解答,你们无外乎都是在围绕着可阅、可用、易于重构、自我提高这些方面在阐述,总之写单元测试是一件好的事情,若是你有能力有时间,那么请尝试一下而且持续的写下去吧。网络
通过一些查阅,mocha + chai 仿佛是一个比较广泛的选择。框架
mocha 是一个测试框架,它对异步代码的追踪测试颇有自信。异步
chain 是一个断言库。函数
此外还有一个 jest,它是一个大而全的测试框架,它使用内置的 matchers 断言。工具
# 新建一个文件夹 mkdir mocha-chai # 进入文件 cd mocha-chai # 初始化 npm init -y # 安装 yarn add mocha chai
接下来准备一个源码文件 index.js
和 测试文件 index.spec.js
。
// index.js module.exports.getAbs = (x, y) => { return Math.abs(x - y) }
为何必须是 .spec.js
?我去查了一下,结果以下:
约定俗成的术语。
Unit Testing Specification
(单元测试基准)的缩写,不少框架默认回去找这些后缀的文件。
官方也给出一段相关的内容,不太肯定是否还有其余处。
Test files can be specified usingspec
, e.g.,"spec": "test/**/*.spec.js"
.
// index.spec.js const assert = require('chai').assert const getAbs = require('./index').getAbs describe('to test getAbs()', () => { it('should return 1 when the value is 1,2', () => { assert.equal(getAbs(1, 2), 1, 'getAbs(1,2) equal 1') }) it('should return 1 when the value is 2,1', () => { assert.equal(getAbs(2, 1), 1, 'getAbs(2,1) equal 1') }) it('should return 0 when the value is 1,1', () => { assert.equal(getAbs(1, 1), 0, 'getAbs(1,1) equal 0') }) })
主要是 test
命令:
"scripts": { "test": "mocha index.spec.js" },
执行:
yarn test
yarn run v1.21.1 $ mocha index.spec.js to test getAbs() √ should return 1 when the value is 1,2 √ should return 1 when the value is 2,1 √ should return 0 when the value is 1,1 3 passing (8ms) Done in 0.46s.
如今,在 index.spec.js 文件中追加一个 it()
:
it('should return 0 when the value is not present', () => { assert.equal(getAbs(), 0, 'getAbs() equal 0') })
以后再次执行:
yarn test
yarn run v1.21.1 $ mocha index.spec.js to test getAbs() √ should return 1 when the value is 1,2 √ should return 1 when the value is 2,1 √ should return 0 when the value is 1,1 1) should return 0 when the value is not present 3 passing (18ms) 1 failing 1) to test getAbs() should return 0 when the value is not present: getAbs() equal 0 + expected - actual -NaN +0 at Context.<anonymous> (index.spec.js:15:12) at processImmediate (internal/timers.js:439:21) error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
总之就是未获得预期的值得意思,很明显这是由于没有传递参数致使的。也就是说在不给函数传递参数的时候,函数的行为有些不符合预期的效果。
因此稍做修改再来一次。
修改 index.js:
// index.js module.exports.getAbs = (x = 0, y = 0) => { return Math.abs(x - y) }
再次执行结果以下:
yarn run v1.21.1 $ mocha index.spec.js to test getAbs() √ should return 1 when the value is 1,2 √ should return 1 when the value is 2,1 √ should return 0 when the value is 1,1 √ should return 0 when the value is not present 4 passing (7ms) Done in 0.47s.
因此说,实际上 unit testing 视状况来看,须要编写不少的断言,上面的测试虽然是经过了,但实际上还有有其余的问题存在的,极端点来说好比传递的参数并非一个数字:
it('should return 0 when the value is not a number', () => { assert.equal(getAbs([1, 2, 3], 3), 0, 'getAbs() equal 0') })
JavaScript 并不像强类型语言那样强硬,因此不少时候即使是错误的使用一个函数也只有在执行起来以后才能浮现错误。
嗯...因此说,单元测试中的断言所能覆盖的状况要相对比较普遍才能够,不然也只是片面的结论而已。
总感受一不当心就会走火入魔...
unit testing 目的是为了使程序更加的健壮,稳定。可是相应的是须要编写更多的代码才能达到这个目的,因此如何正确的把握这个度,应该是一个值得思考的问题。
因此也只有更多的实践才能够找出一个比较满意的答案吧。