欢迎,你可能在搜索如何用Jest调试你的测试。我很高兴你能找到这篇博文,因为你将要学习7种在终端调试Jest测试的方法。每个人都知道,你可以用VSCode或WebStorm等IDE轻松做到这一点,但如果你不使用它们呢?你如何去调试它们呢?剧透一下--不是用console.log()
。
1.标准方式
如果你在Jest文档中搜索方法,它会告诉你以下内容:
- 进入一个基于Chromium的浏览器,打开
chrome://inspect
。 - 点击 "Open dedicated DevTools for Node",就像下面的屏幕截图:
- 在你的代码中的某个地方放一个
debugger
语句(测试或生产的)。 - 运行
node --inspect-brk node_modules/.bin/jest --runInBand [any other arguments here]
。
然后,你的测试应该运行并停止在你在步骤2中打开的DevTools的调试器上。实际上,由于--inspect-brk
,这个过程会在你运行后立即停止,但我们稍后会提到这个问题。
通常在项目中,你并不是在使用原始的Jest命令。有时它被包裹在一些其他的库中,或者使用一些额外的配置来启动它。如果你是这种情况,让我们深入研究,找出不同的方法来调试和检查我们的测试。
💡在我们了解其他调试方法时,请打开专门的DevTools for Node窗口。
2.没有初始中断
如果你看一下,这里的大部分魔法都是由Node Inspector完成的。Node Inspector最酷的地方在于,当你做node --inspect
,一个Node.js进程会在127.0.0.1:9229
,听一个调试客户端。这一变化在2016年得到了引入。并允许每个人都能轻松地检查他们的进程。
在我们上一节的例子中,我们使用了node --inspect-brk ...
。使用--inspect-brk
标志会在用户代码开始前中断。在我的例子中,我并不关心我的测试一开始就停止,只是求助于普通的node --inspect
。node --inspect
会在你放置debugger
的地方中断,而不是在启动时立即做。从现在开始,让我们用这个方法行动吧。我们的调试命令将是:
$ node --inspect node_modules/.bin/jest --runInBand
由于node_modules
的位置可能取决于操作系统,我们可以让它变得不可知,并使用yarn bin
或npm bin
。在我的例子中,我将像这样使用npm bin
:
$ node --inspect $(npm bin)/jest --runInBand
3.调试TypeScript测试
如果你现在正在使用TypeScript,如果你试图运行:
$ node --inspect $(npm bin)/jest --runInBand
你可能会得到一个错误,因为TypeScript测试没有被转译成JavaScript。请确保你在jest.config.js
,类似于以下配置的Jest:
module.exports = {
roots: ["<rootDir>/src"],
testMatch: [
"**/__tests__/**/*.+(ts|tsx|js)",
"**/?(*.)+(spec|test).+(ts|tsx|js)",
],
transform: {
"^.+\\.(ts|tsx)$": "ts-jest", // The important part right here
},
}
我们告诉Jest使用ts-jest
来转换.ts
和.tsx
文件。如果你没有ts-jest
,你可以用npm install -D ts-jest
来安装它,你应该就可以了。我做了一个样本库,你可以在这里试用。
4.调试的最佳方法
好了,这一节的标题承诺了很多,请听我说。如果你没有听说过Jest的观察模式,你会喜欢这个。我在写代码的时候,大部分时间都在运行jest --watch
。观察模式的优秀之处在于,它将观察你所做的任何改变,并运行相关测试。要在观察模式下调试你的测试,你可以输入以下内容:
$ node --inspect $(npm bin)/jest --watch --no-cache --runInBand
让我们在这里把Jest的参数分解一下:
--watch
从Jest中启动观察模式,这非常酷。--no-cache
将确保我们的代码被正确重载。你可以尝试不使用它,但观察模式可能无法正常工作。--runInBand
- 好的,这个标志从一开始就一直跟着我们。它的存在是为了确保所有的测试在一个进程中串行运行,而不是创建子进程。有一个进程使得 "检查 "测试成为可能。node --inspect
你也可以结合其他Jest命令,如运行一个测试:
$ node --inspect $(npm bin)/jest --runTestsByPath src/index.test.ts --runInBand
但不要忘记附加--runInBand
,或者只附加-i
,以确保Node.js检查器发挥其魔力。
5.CRA怎么办?
如果你使用create-react-app (CRA),并让你的测试脚本使用react-scripts测试,那么调试对你来说会有点不同。一个推荐的方法是像这样给package.json
,添加一个新的脚本:
"scripts": {
...,
"test:debug": "react-scripts --inspect test --runInBand --no-cache"
}
现在,每当你运行npm run test:debug
,Jest就会以观察模式运行,并在你放置debugger
的地方停止。当然,你需要打开一个专门的DevTools for Node.js,正如我们在第一节所描述的那样。
6.从命令行调试
好了,你得到了基于Chromium的浏览器和DevTools的初始调试器的工作。但是,如果你是一个命令行爱好者,你可能在想一个没有DevTools的方法。好消息是,这是可以做到的。幸运的是,我们有node inspect
,为我们启动一个命令行调试器。试着只运行下面的命令:
$ node inspect $(npm bin)/jest --runInBand
我在我做的例子 repo 中运行了这个,这是我得到的结果:
$ node inspect $(npm bin)/jest --runInBand
< Debugger listening on ws://127.0.0.1:9229/be2d3410-48ad-46fb-a345-bb37339b5e38
< For help, see: https://nodejs.org/en/docs/inspector
< Debugger attached.
Break on start in node_modules/jest/bin/jest.js:9
7 */
8
> 9 const importLocal = require('import-local');
10
11 if (!importLocal(__filename)) {
debug>
检查器在node_modules/jest/bin/jest.js:9
内的第一行就停止了。我们可以通过输入cont
或直接输入c
来继续调试:
$ node inspect $(npm bin)/jest --runInBand
< Debugger listening on ws://127.0.0.1:9229/be2d3410-48ad-46fb-a345-bb37339b5e38
< For help, see: https://nodejs.org/en/docs/inspector
< Debugger attached.
Break on start in node_modules/jest/bin/jest.js:9
7 */
8
> 9 const importLocal = require('import-local');
10
11 if (!importLocal(__filename)) {
debug> cont
break in src/index.test.ts:6
4 test("add", function () {
5 var result = index_1.add(1, 2);
> 6 debugger;
7 expect(result).toEqual(3);
8 });
debug>
现在,检查器在我们测试代码中的debugger
语句处停止了。我们可以输入help
,熟悉所有可以在这里输入的命令。我不会去看所有的命令,但我要提到repl
命令。在调试器内输入repl
,你将进入 "读取-评估-打印-循环"(REPL)模式,在那里你可以评估变量。如果我在我的例子中这样做,我将得到以下结果:
$ node inspect $(npm bin)/jest --runInBand
< Debugger listening on ws://127.0.0.1:9229/be2d3410-48ad-46fb-a345-bb37339b5e38
< For help, see: https://nodejs.org/en/docs/inspector
< Debugger attached.
Break on start in node_modules/jest/bin/jest.js:9
7 */
8
> 9 const importLocal = require('import-local');
10
11 if (!importLocal(__filename)) {
debug> cont
break in src/index.test.ts:6
4 test("add", function () {
5 var result = index_1.add(1, 2);
> 6 debugger;
7 expect(result).toEqual(3);
8 });
debug> repl
Press Ctrl + C to leave debug repl
> result
3
>
而这些就是在命令行中检查你的代码的基础。开发者体验(DX)可能没有打开DevTools的时候那么好,在那里你可以通过悬停在变量上获得变量的值,但它仍然是一个不错的选择。让我们在下一节看看我们如何从命令行中打开DevTools。
7.一体化的解决方案 - ndb
ndb是一个用于改善Node.js的调试体验的库。你可以用npm install -g ndb
全局安装它,也可以用npm install -D ndb
本地安装它。我在我的Abacus repo上用全局命令试了一下:
$ ndb $(npm bin)/jest --watch --no-cache --runInBand
而且效果很好。只要你输入它,它就会为你打开DevTools。它也比普通的node --inspect
,执行得更快。ndb的伟大之处在于,你可以很容易地运行你的脚本,用于package.json
。我成功地运行了以下内容。
$ ndb npm run test -- --watch --no-cache --runInBand
我相信使用ndb的方法对那些想从命令行做所有事情的人来说是最有吸引力的。它省去了你去浏览器打开DevTools for Node.js。ndb为你做这些。
最后的思考
现在就这些了,伙计们。你应该能够选择一种方法来调试你的Jest测试。在Jest中调试测试的想法 "困扰 "了我很久,我很高兴我找到了各种解决方案,并能与大家分享它们。