使用node-inspector调试Jest测试用例

40

有没有办法使用node-inspector调试Jest的单元测试?有时候可以逐步执行以查看为什么测试失败。

我已经尝试了几种方法


node-debug jest --runInBand 

从控制台开始,以及首先启动检查器。

$ node-inspector
$ node --debug-brk .\node_modules\jest-cli --runInBand

然后导航至http://127.0.0.1:8080/debug?port=5858

我发现有时候(大约10次中有1次),调试器会打开jest源文件,可以对它们进行调试。一般情况下,调试器中的脚本只包含一个“无域名”文件夹和另一个不相关的文件夹。此外,测试脚本本身永远不会在调试器中加载。

有人以前尝试过这样做吗?

4个回答

16
看起来问题在于 jest 使用了 harmonize,它会生成一个子进程以确保使用了 --harmony 选项。

harmonize/harmonize.js, 第30-35行

var node = child_process.spawn(process.argv[0], ['--harmony'].concat(process.argv.slice(1)), {});
node.stdout.pipe(process.stdout);
node.stderr.pipe(process.stderr);
node.on("close", function(code) {
    process.exit(code);
});

我能够成功调试jest测试(尽管使用JSX转换的测试非常缓慢),方法是注释掉jest用来生成harmonized进程的代码。

node_modules/jest-cli/bin/jest.js,文件的最后几行:

if (require.main === module) {
  //harmonize();                  <--- comment out
  _main(function (success) {
    process.exit(success ? 0 : 1);
  });
}

然后你可以运行:
$ node-debug --nodejs --harmony ./node_modules/jest-cli/bin/jest.js --runInBand

Jest依赖于存在--harmony标志,因此我们需要使用--nodejs --harmony将其添加回来。我们还添加了--runInBand,以使测试按顺序而非并行运行。

这会打开Web调试器,您可以调试测试,但是要到达所需的测试可能会非常慢。如果有人知道如何加快速度,请在评论中指出,我会更新我的答案。

您可以将此添加到您的package.json中以更轻松地启动:

...
    scripts: {
        "test": "jest",
        "test-debug": "node-debug --nodejs --harmony ./node_modules/jest-cli/bin/jest.js --runInBand"
    }
...

当然,这种解决方案的主要问题是编辑jest源代码。我会考虑如何提交pull request以使其生效。
在这里创建了Github Issue:https://github.com/facebook/jest/issues/152

对我来说非常好用!不需要monkeypatch,移除--runInBand似乎可以更快地进行测试。感谢脚本提示。 - Phil Toms
是的,我的PR被拒绝了,因为你刚才提到的那行代码检查了Proxy,但我认为如果没有手动添加--harmony标志,它对我来说不起作用,但最近我还没有尝试过。如果我可以验证它在没有猴子补丁的情况下工作,我会更新这个答案。 - Sean Adkinson
有没有逐步指南来使用WebStorm调试器使其正常工作? - SuperUberDuper

14

现在,Node >= 6.3 官方支持此功能。
引用 Jest 文档:在任何测试中加入 debugger; 语句,然后在项目目录中运行:

node --debug-brk --inspect ./node_modules/.bin/jest -i [any other arguments here]

这将输出一个链接,您可以在Chrome中打开。打开链接后,Chrome开发者工具将被显示,并且在Jest CLI脚本的第一行设置了断点(这样做只是为了给您打开开发者工具的时间,并防止Jest在您没有时间执行之前执行)。单击屏幕右上角看起来像“播放”按钮的按钮以继续执行。当Jest执行包含debugger语句的测试时,执行将暂停,您可以检查当前范围和调用堆栈。

注意:使用-i CLI选项确保Jest在同一进程中运行测试,而不是为单个测试生成进程。通常,Jest会在多个进程之间并行运行测试,但同时调试多个进程很困难。

有关V8检查器的更多信息,请访问此处:https://nodejs.org/api/debugger.html#debugger_v8_inspector_integration_for_node_js


3
这看起来很有前途,我试了一下,但是它从未停在调试器语句上。有什么想法吗? - hakunin
1
一样的情况。脚本能够正确启动,我也可以打开浏览器窗口并点击类似播放按钮的东西...但是调试器从未被触发 :| - Belgor
1
对我来说,Jest的路径是不同的,所以我的命令是node --debug-brk --inspect ./node_modules/jest/bin/jest -i --env jest-environment-node-debug - Nitin Jadhav
使用这种方法,我也没有看到jest在我的规范中停止在“debugger”语句上。 - dmarr
1
它在我的电脑上可以运行,但是在运行测试时出现了“window未定义”的错误。 - Tim
显示剩余2条评论

5
使用 Node 7.4.0、Jest 18.x 和 jest-environment-node-debug 包(来自this comment),现在可以使用 Chrome DevTools 来调试 Jest 测试:
$ npm install -D jest-environment-node-debug
$ node --inspect-brk ./node_modules/.bin/jest -i --env jest-environment-node-debug

这是最佳答案,其他的都已经过时了。 - brianyang
使用 --inspect-brk 没有启动测试(它会在用户代码开始之前中断),但是使用 --inspect 可以。 - Bernardo Dal Corno

4
这是一个Gruntfile.js的配置,可以使用Grunt自动化@Sean的答案。
grunt testd

或者

grunt testd --tests=MyTestName

或者

grunt testd --tests=MyTestName,AnotherTestName

需要安装 "node-inspector"(必须全局安装以获取 node-debug 命令在您的路径中),"lodash","jest-cli" 和 "grunt-shell" Node 模块。

var _ = require('lodash');

var commaSplitToRegex = function(input) {
  return _.map(input.split(','), function(part) {
    return '(' + part + ')';
  }).join('|');
};

var getTestRegex = function(tests) {
  if (tests) {
    return '.*' + commaSplitToRegex(tests) + '.*';
  }

  return '.*';
}

module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-shell');

  grunt.initConfig({
    shell: {
      jestd: {
        command: function() {
          var testsRegex = getTestRegex(grunt.option('tests'));
          var cmd = 'node-debug --nodejs --harmony ./node_modules/jest-cli/bin/jest.js --runInBand --config="test_utils/jest.json"';

          if (testsRegex) {
            cmd += ' "' + testsRegex + '"';
          }

          return cmd;
        }
      },
      monkeypatchjest: {
        command: 'sed -i.bak s\\/harmonize\\(\\)\\;\\/\\\\/\\\\/wtf\\/g ./node_modules/jest-cli/bin/jest.js'
      },
      unmonkeypatchjest: {
        command: 'sed -i.bak s\\/\\\\/\\\\/wtf\\/harmonize\\(\\)\\;\\/g ./node_modules/jest-cli/bin/jest.js'
      }
    }
  });

  grunt.registerTask('testd', 'Run tests with debugger.', ['shell:monkeypatchjest', 'shell:jestd']);
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接