Node有哪些可以运用的测试框架?下面本篇文章给大家整理分享一些Node.js测试框架,希望对大家有所帮助! node.js极速入门课程:进入学习 编者按:本文作者是蚂蚁集团 Node.js 工程师天猪,首先会介绍下各个部分常用的类库,在文末将讨论下,单元测试是否有必要,欢迎一起探讨。 mocha 和 jest 用的比较多。官方新出了个 node test 还在打磨中,未来可期。 虽然有这么多 Runner,不过它们的输出标准都是 TAP 格式,然后通过不同 Reporter 输出结果。 光写单测还不够,我们需要知道是否覆盖了代码的所有分支流程,所以一般还要搭配代码覆盖率工具。 之前是 istanbuljs,后面作者重写了个 nyc,它们主要承担 2 个职责:一是把代码进行转译从而插入打桩代码,二是支持各种 Reporter 来生成覆盖率报告。 再后来 V8 内置了覆盖率统计 ,即无需再转译代码了,原生支持覆盖率数据采集。 然后又是这个作者写了个 c8 专注于生成覆盖率报告。 校验变量结果,必不可少的要用到 assert。 历史上出现过:expect.js 、should.js、chai 以及 power-assert,jest 也内置了自己的 expect。 不过现在 Node.js 官方的 assert/strict 其实也还不错。 其中 power-assert 是我们 EggJS 一直在用的,我很多年前也安利过:《可能是最好的 JS Assert 库 - 皇帝的新衣》。 PS:如果要校验文件内容的话,我也写过一个 assert-file,欢迎品尝。 因为是单元测试,所以经常会需要模拟环境或下游的响应。 sinonjs 还不错,支持 mock 和 stub 等。jest 同样也内置了自己的 mock 库。 如果是 HTTP 测试的话,nock 很强大,可以帮你 Mock 服务端响应。 不过 Node.js 官方出的 undici 请求库也内置了 Mock 能力。 还有个术语叫 snapshot,即在运行的时候把数据 dump 下来,直接作为下次测试的 mock 数据,能一定程度上提升编写测试的效率。 测试 HTTP Server 场景,必不可少的就是 supertest 这个库。 Node.js 的一大使用场景是命令行 CLI,如 Webpack、Babel 这些,它们本身也是需要有单测的。 这块推荐我们写的: GitHub - node-modules/clet: Command Line E2E Testing GitHub - node-modules/coffee: Test command line on Node.js import { runner, KEYS } from 'clet'; it('should works with boilerplate', async () => {
await runner()
.cwd(tmpDir, { init: true })
.spawn('npm init')
.stdin(/name:/, 'example') // wait for stdout, then respond
.stdin(/version:/, new Array(9).fill(KEYS.ENTER))
.stdout(/"name": "example"/) // validate stdout
.notStderr(/npm ERR/)
.file('package.json', { name: 'example', version: '1.0.0' }) // validate file
}); 轻量的爬页面,可以直接用 HTTP 请求库即可,推荐 undici。 模拟浏览器真实执行的话,早期是 selenium 和 phantomjs。 然后 Google 官方出了 puppeteer,由于有 Chromium 的积累,基于 devtools-protocol 协议,很快就广受欢迎,干掉了前两者。同类的竞品还有 playwright 和 cypress。 顺便安利下 macacajs,一个多端的测试工具,除了浏览器外还支持移动 APP 和桌面 APP 的测试,是语雀团队的工程师开源的。 我们写开源的时候,经常需要自动化的持续集成服务来帮我们测试。 这个领域的玩家有:Travis 、Appveyor、GitHub Actions 等。 现在基本上都是用 GitHub Actions 了,集成程度太爽了。 毋庸置疑,单元测试是非常重要的,它是一名合格的程序员的必要能力和职业素养。 当然,我们也不是原教旨的 100% 覆盖率狂徒,很多情况下需要追求 ROI 的平衡点。 首先,我先纠正一个常见的新人观点:写单元测试很浪费时间? 实际上,写单元测试反而会节省你的时间,之所以有那个反直觉的观点,往往之于对比的条件不客观。我们需要考虑二次修改代码后,在同等质量要求的情况下,回归的成本。 公平的对比,除了考虑『写单测时间』外,容易忽略的是『每次修改代码后回归测试的时间』: 写单测的情况下,前期造好各种分支 Mock,回归测试的时间就是敲一下键盘; 不写单测的情况下,你需要把代码更新到应用中,然后手动模拟各种情况来测试,譬如要打开浏览器,点击很多不同的地方。 这两个耗时如何,一目了然。 无非是 前期投入+维护成本+对回归质量的重视程度,权衡之后的决策,每个公司都有自己的尺度。 当然,我提的很多场景都是 框架类库(包括前端和 Node.js)、服务端应用、命令行工具等方面,确实在一些变化较大的前端偏 UI 展示的应用或者快上快下的活动页面,对应的单测维护成本确实很高,这时候可以基于 ROI 去适当放弃某些非核心分支的单测,这是合理的。 但我们要清楚这是不得已的取舍,我们可以通过各种手段去降低单测的维护成本,但我们唯独不能去宣称单元测试没什么用。 在前端领域还有一种半自动化回归的测试,就是基于 diff 的方式去自动化对比,然后提醒 Owner 去注意变化影响。这就跟上面那些工具类库一样,都是来帮助减少编写单测的成本的。 这也是一个错误的观点,单元测试是应该程序员自己来写的,因为是你自己的代码,要为此而负责,这是一种职业素养。任何一个稍微有点规范的团队,提交代码都是需要有 CI 测试的,否则无法 有质量的 Code Review 协作。 测试同学负责的是集成测试、回归测试、端到端测试等更大层面的工作。 分工不同,请不要甩锅。 单元测试很有必要性,编写单测是程序员的基本职业素养,能写尽量写,在个别场景可以根据 ROI 进行取舍。常用的类库和工具
测试用例执行器
$ mocha
test/egg-view-ejs.test.js
render
✓ should render with locals
✓ should render with cache
✓ should render with layout
✓ should render error
renderString
✓ should renderString with data
✓ should renderString error
6 passing (398ms)
覆盖率统计
Assert 类库
const assert = require('power-assert');
describe('test/showcase.test.js', () => {
const arr = [ 1, 2, 3 ];
it('power-assert', () => {
assert(arr[1] === 10);
});
});
// output:
4) test/showcase.test.js power-assert:
AssertionError: # test/showcase.test.js:6
assert(arr[1] === 10)
| | |
| 2 false
[1,2,3]
[number] 10
=> 10
[number] arr[1]
=> 2
Mock & Stub 类库
nock('http://www.example.com')
.post('/login', 'username=pgte&password=123456')
.reply(200, { id: '123ABC' })
HTTP 测试类库
describe('GET /users', function() {
it('responds with json', async function() {
return request(app)
.get('/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.then(response => {
assert(response.body.email, '[email protected]');
});
});
});
命令行测试类库
网页自动化测试工具
持续集成服务
探讨:单元测试是否有必要?
1. 写单元测试很浪费时间?
2. 单元测试不应该程序员写?
so...