添加测试框架
-
接上文,仍旧在 abc-cli 项目中
-
参考:https://blog.csdn.net/Tyro_java/article/details/136438882
-
现在要在脚手架项目中安装测试工具,选择 jest
-
数据:Weekly Downloads 19,759,155 (动态)
-
可见是一个比较流行的测试库,现在安装它
-
$
npm i jest execa -D -w packages/cli
-
注意,这里的
-D
它是开发依赖,用于测试 -
之后,在 abc-cli/packages/cli/package.json 中的 scripts 进行修改
js{ "scripts": { "test": "jest" } }
-
在 abc-cli/packages/cli/tests/cli.test.js 中编写
jstest('run error command', () => { expect(1 + 1).toBe(2); })
-
进入 abc-cli/packages/cli 目录下,执行 $
npm run test
, 查看输出shell$ npm run test > @abc.com/cli@0.0.0 test > jest PASS __tests__/cli.test.js ✓ run error command (2 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 0.329 s Ran all test suites.
-
好,看起来一切正常,现在我们来测试CLI内部的一些API
jsimport path from 'node:path'; import { execa } from 'execa'; const CLI = path.join(__dirname, '../bin/cli.js'); const bin = () => () => execa(CLI); test('run error command', () => { expect(1 + 1).toBe(2); }) test('run cli', async () => { const ret = await bin()(); console.log(ret); })
-
这里拿到 cli 中的api,进行执行测试,但是发现报错了
shellDetails: /Users/xx/abc-cli/packages/cli/__tests__/cli.test.js:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import path from 'node:path'; ^^^^^^ SyntaxError: Cannot use import statement outside a module at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1505:14)
-
可以看到,它这里把整个代码当做 commonjs 来运行, jest本身提供的就是 commonjs 的方式,这里涉及到了如何让 jest 支持 esm
-
jest 默认集成了 babel, 我们利用这个特性,创建 babel 的配置文件,新建 abc-cli/packages/cli/babel.config.cjs
-
安装 babel, 在 abc-cli 目录中,$
npm i @babel/core @babel/preset-env -D -w packages/cli
-
编辑 babel.config.cjs, 注意,这里是 cjs 代表在ESM中使用commonjs规则
jsmodule.exports = { presets: [ ['@babel/preset-env'] ] }
-
之后,在同级目录添加 jest.config.cjs
jsmodule.exports = { transformIgnorePatterns: [] }
-
再次在 abc-cli/packages/cli 目录下,执行 $
npm run test
, 查看输出 -
虽然看似报错,但是是这个命令的执行结果
shell> @abc.com/cli@0.0.0 test > jest FAIL __tests__/cli.test.js ✓ run error command (2 ms) ✕ run cli (165 ms) ● run cli Command failed with exit code 1: /Users/Wang/Desktop/DD/abc-cli/packages/cli/bin/cli.js abc.com success log test version 0.0.0 Usage: abc-cli <command> [options] Options: -V, --version output the version number -d, --debug 是否开启调试模式 (default: false) -h, --help display help for command Commands: init [options] [name] init project help [command] display help for command at makeError (node_modules/execa/lib/error.js:60:11) at _callee$ (node_modules/execa/index.js:124:35) at call (node_modules/execa/index.js:2:1) at Generator.tryCatch (node_modules/execa/index.js:2:1) at Generator._invoke [as next] (node_modules/execa/index.js:2:1) at asyncGeneratorStep (node_modules/execa/index.js:2:1) at asyncGeneratorStep (node_modules/execa/index.js:2:1) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 passed, 2 total Snapshots: 0 total Time: 0.792 s, estimated 2 s Ran all test suites.
-
现在就可以继续完善了,修改 abc-cli/packages/cli/tests/cli.test.js
jsimport path from 'node:path'; import { execa } from 'execa'; const CLI = path.join(__dirname, '../bin/cli.js'); const bin = () => (...args) => execa(CLI, args); test('run error command', () => { expect(1 + 1).toBe(2); }) test('run cli', async () => { const ret = await bin()(iii); console.log(ret); })
-
执行 $
npm run test
, 查看输出shell> @abc.com/cli@0.0.0 test > jest console.log { command: '/Users/Wang/Desktop/DD/abc-cli/packages/cli/bin/cli.js iii', escapedCommand: '"/Users/Wang/Desktop/DD/abc-cli/packages/cli/bin/cli.js" iii', exitCode: 0, stdout: '', stderr: 'abc.com success log test version 0.0.0\nabc.com ERR! 未知的命令:iii ', all: undefined, failed: false, timedOut: false, isCanceled: false, killed: false } at log (__tests__/cli.test.js:13:10) PASS __tests__/cli.test.js ✓ run error command (2 ms) ✓ run cli (141 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 0.744 s, estimated 1 s Ran all test suites.
-
这样,看到用例都通过了,但是这是一个没有注册的命令
-
继续优化, 编写 abc-cli/packages/cli/tests/cli.test.js 如下
jsimport path from 'node:path'; import { execa } from 'execa'; const CLI = path.join(__dirname, '../bin/cli.js'); const bin = () => (...args) => execa(CLI, args); // 正常测试 test('run normal test', () => { expect(1 + 1).toBe(2); }) // 测试 cli 未注册命令 test('run cli', async () => { const { stderr } = await bin()('iii'); expect(stderr).toContain('未知的命令:iii') }) // 测试 --help test('test --help', async () => { let error = null; try { await bin()('--help'); } catch(e) { error = e; } expect(error).toBe(null); }) // 测试 -V test('test --version', async () => { const { stderr } = await bin()('-V'); expect(stderr).toContain(require('../package.json').version) }) // 测试是否开启 debug 模式 test('test --debug', async () => { let error = null; try { await bin()('-d'); } catch(e) { error = e; } expect(error.message).toContain('launch debug mode'); })
-
运行 $
npm run test
查看输出结果shell> @abc.com/cli@0.0.0 test > jest PASS __tests__/cli.test.js ✓ run normal test (2 ms) ✓ run cli (148 ms) ✓ test --help (140 ms) ✓ test --version (131 ms) ✓ test --debug (142 ms) Test Suites: 1 passed, 1 total Tests: 5 passed, 5 total Snapshots: 0 total Time: 1.218 s Ran all test suites
-
通过以上,我们把整个测试框架和一些基础用例编写完成,在实际场景中可以继续挖掘出更多用法
-
相关代码参考:v_test