在终端调试Jest测试的7种方法

864 阅读6分钟

欢迎,你可能在搜索如何用Jest调试你的测试。我很高兴你能找到这篇博文,因为你将要学习7种在终端调试Jest测试的方法。每个人都知道,你可以用VSCode或WebStorm等IDE轻松做到这一点,但如果你不使用它们呢?你如何去调试它们呢?剧透一下--不是用console.log()

1.标准方式

如果你在Jest文档中搜索方法,它会告诉你以下内容:

  1. 进入一个基于Chromium的浏览器,打开chrome://inspect
  2. 点击 "Open dedicated DevTools for Node",就像下面的屏幕截图:
  3. 在你的代码中的某个地方放一个debugger 语句(测试或生产的)。
  4. 运行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 --inspectnode --inspect 会在你放置debugger 的地方中断,而不是在启动时立即做。从现在开始,让我们用这个方法行动吧。我们的调试命令将是:

$ node --inspect node_modules/.bin/jest --runInBand

由于node_modules 的位置可能取决于操作系统,我们可以让它变得不可知,并使用yarn binnpm 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中调试测试的想法 "困扰 "了我很久,我很高兴我找到了各种解决方案,并能与大家分享它们。