Jest 命令行窗口中的指令
在学习Jest单元测试入门的时候,我们给Jest命令提供了一个参数 --watchAll, 让它监听测试文件或测试文件引入的文件的变化,从而时时进行测试。但这样做也带来一个问题,只要改变一点内容,Jest就会把所有的测试都跑一遍,有点浪费资源。有没有可能对--watchAll模式进行进一步的优化,那是有的, 在什么地方呢?在命令窗口中。执行npm run test, 测试完成后,你会发现还有很多提示(Watch Usage),这些就是对--watchAll模式的优化
Press f to run only failed tests. 按f 键,进入一种模式,它只跑失败的测试用例。当我们执行npm run test 的时候,发现有一个测试失败了,这时我们只想跑失败的测试用例,那就按f吧。演示一下,随便把一个测试用例改为错误,比如 把request 的mock 改为name: 'jason'
jest.mock('request', () => { return (url, callback) => { callback(null, 'ok', {name: 'jason'}) } });
这时测试重新跑了一遍了(watchAll 模式),命令窗口中显示了错误, 并且在最下面显示press w to show more, 同时光标在闪烁,等待输入。此时按w, 显示了上图中的内容,再按f, 只跑了失败的测试,因为三个测试skipped 了, 当然肯定还是有错误,因为我们还没有修改测试代码
此时修改测试代码到正确并保存,测试成功,不过它也是跑了刚才错误的测试。此时你再修改func.test.js 文件或其它测试用例,发现测试不会再运行了,显示No failed test found.
这时就要退出f 模式了, Jest 也提示了,按f键退出 ‘只跑失败测试’ 的模式。此时按f, 重新回到了watchAll 模式,把所有的测试用例重新跑了一遍。
f 模式的使用就是,npm run test 有失败测试,按f, 修改失败到成功,再按f 退出该模式。
Press o to only run tests related to changed files. 按o ,只跑改变文件中的测试。Jest 会实时监听文件的变化,如果哪个文件发生变化,它会跑哪个文件中的测试,其它没有变化的文件中的测试,它是不会跑的。那Jest是怎么知道哪个文件发生变化的呢?它自己不知道,需要借助git. 因为git 就是追踪文件变化的。只要把工作区和仓库区的代码一对比,就知道哪个文件发生变化了。那就要把项目变成git 项目。在根目录下,先建.gitignore 文件,再执行git init, 把项目变成git 项目,否则会把node_modules 放到 git 仓库中。此时为了对比,把func.test.js拆分为三个测试文件,fetchData.test.js, forEach.test.js, math.test.js
jest.mock('request', () => { return (url, callback) => { callback(null, 'ok', {name: 'sam'}) } }); const fetchData = require('./func').fetchData; test('should return data when fetchData request success', () => { return fetchData().then(res => { expect(res).toEqual({name: 'sam'}) }) })
const forEach = (array, callback) => { for (let index = 0; index < array.length; index++) { const element = array[index]; callback(element); } } test('should call callback when forEach', () => { const mockFun = jest.fn(); // mock 函数 const array = [1, 2]; forEach(array, mockFun); // 用mock函数代替真实的回调函数 expect(mockFun.mock.calls.length).toBe(2) })
const math = require('./func'); test("calls math.add", () => { const addMock = jest.spyOn(math, "add"); // override the implementation addMock.mockImplementation(() => "mock"); expect(addMock(1, 2)).toEqual("mock"); // restore the original implementation addMock.mockRestore(); expect(addMock(1, 2)).toBeUndefined(); }); test('should call add', () => { function callMath(a, b) { return math.add(a + b); } const addMock = jest.spyOn(math, 'add'); callMath(1, 2); expect(addMock).toBeCalled(); // toBeCalled, 就是函数有没有被调用。 })
git add . and git commit -m "init git" 把文件提交到git 仓库。这时再执行npm run test, 启动测试,直接按o ,进入到o 模式, 可以看到提示,没有文件发生变化。
这时更改一个文件,如forEach 加一个空行,看一下控制台,只有forEach.test.js 测试文件执行了,其它测试文件并没有执行, 再改一个fetchData.test.js 文件,两个测试文件执行了,还是只跑改变的文件中的测试。这时让我想起了jest 命令的另一个参数,--watch, -o 模式 不就是--watch 吗。把package.json 中的 --watchAll 改成 --watch
"scripts": { "test": "jest --watch" },
重新启动npm run test, 有了-a模式,run all the tests, 这不就是--watchAll, 原来 --watch, --watchAll, a 模式,o 模式,是这样时行互通的。
再看一下p, 按照文件名执行测试,我们提供一个文件名,它只会对该文件进行测试,可以使用正则表达式来匹配文件名。按p, 提示输入pattern, 再输入fetch, 它就会用fetch 去匹配所有的测试文件名,找到了fetchData.test.js 测试文件,然后它就执行了。如果找不到任何测 试文件,它什么测试都不会执行。
t 则是匹配的test 名字,每一个test 都有一个描述,这个描述可以称之为test 的名字。提供一个test 的名字,它只跑这个test,用法和p 一样。
q 退出watch, enter 就是跑一次单元测试,无论是在什么模式下,只要按enter,就会跑一次对应模式的测试。