自动化测试:DevTools mochitests

运行 DevTools 的整个浏览器 mochitests 套件(坐下来放松)

./mach mochitest --subsuite devtools --tag devtools

运行特定工具的浏览器 mochitests 套件

./mach mochitest devtools/client/<tool>

例如,运行所有调试器浏览器 mochitests

./mach mochitest devtools/client/debugger

运行特定的 DevTools mochitest

./mach mochitest devtools/client/path/to/the/test_you_want_to_run.js

请注意,mochitests 在运行时**必须**获得焦点。测试在浏览器中运行,看起来像有人在手动测试您的代码。如果浏览器失去焦点,测试将在一段时间后停止并失败。(再次,坐下来放松)

如果您希望运行 mochitests 而无需关心焦点,并在运行时能够触摸您的电脑

./mach mochitest --headless devtools/client/<tool>

您也可以只运行单个测试

./mach mochitest --headless devtools/client/path/to/the/test_you_want_to_run.js

跟踪 JavaScript

您可以使用 DEBUG_STEP 环境变量记录 mochitest 脚本中执行的所有行。这将帮助您

  • 如果测试卡在某些异步等待代码上,它在等待哪一行,

  • 将测试脚本执行可视化与各种日志和断言日志进行比较。

请注意,它仅适用于导入 devtools/client/shared/test/shared-head.js 模块的 Mochitests,大多数 DevTools 浏览器 mochitests 使用该模块。

这种方式

DEBUG_STEP=true ./mach mochitest browser_devtools_test.js

或者其他方式

./mach mochitest browser_devtools_test.js --setenv DEBUG_STEP=true

这将记录以下行

[STEP] browser_target_command_detach.js @ 19:15   ::   const tab = ↦ await addTab(TEST_URL);

这表明测试脚本在第 19 行和第 15 列即将执行。'↦'突出显示了精确的执行列。

您可以传递毫秒数而不是 true,每个测试行将暂停给定的时间。使用此功能时请小心,因为它将在每个测试行上暂停事件循环并允许处理其他事件。这将导致测试以一种不现实的方式运行,否则不会发生这种情况。

DEBUG_STEP=250 ./mach mochitest browser_devtools_test.js

mochitest 脚本的每一行将暂停 1/4 秒。

最后但并非最不重要的是,此功能可通过以下方式在 try 上使用

./mach mochitest try fuzzy devtools/test/folder/ --env DEBUG_STEP=true

一旦您找到有问题的行,或者想了解有关 mochitest 特定行上发生的事情的更多信息,您就可以使用 DEBUG_TRACE_LINE 环境变量。它需要正在运行的 mochitest 文件的行号,它将跟踪从该代码行运行的所有 JavaScript 代码。

DEBUG_TRACE_LINE=42 ./mach mochitest browser_devtools_test.js

这将记录类似以下内容

 0:17.14 GECKO(94170)  [STEP] chrome://mochitests/content/browser/devtools/client/webconsole/test/browser/head.js
 0:17.14 GECKO(94170)  [STEP] ───────────────────────────────────────────────────────────────────────────────────
 0:17.14 GECKO(94170)  [STEP] 73:36   | async function openNewTabAndConsole↦ (url, clearJstermHistory = true, hostId) {
 0:17.15 GECKO(94170)  [STEP] 74:19   |   const toolbox = ↦ await openNewTabAndToolbox(url, "webconsole", hostId);
 0:17.15 GECKO(94170)  [STEP]
 0:17.15 GECKO(94170)  [STEP] chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js
 0:17.15 GECKO(94170)  [STEP] ──────────────────────────────────────────────────────────────────────────────
 0:17.15 GECKO(94170)  [STEP] 1273:36 | async function openNewTabAndToolbox↦ (url, toolId, hostType) {
 0:17.15 GECKO(94170)  [STEP] 1274:15 |   const tab = ↦ await addTab(url);
 0:17.15 GECKO(94170)  [STEP] 531:22  | async function addTab↦ (url, options = {}) {
 0:17.15 GECKO(94170)  [STEP] 532:3   |   ↦ info("Adding a new tab with URL: " + url);

您可以看到函数之间的执行流程,以及函数调用的进度。与 DEBUG_STEP 类似,'↦'符号突出显示了精确的执行位置。

如果此帮助程序不够。您还可以从任何特权代码库中的任何位置手动生成跟踪器,使用以下代码段

const { JSTracer } = ChromeUtils.importESModule(
  "resource://devtools/server/tracer/tracer.sys.mjs",
  { global: "contextual" }
);
// You have to at least pass an empty object to startTracing,
// otherwise, all the attributes at optional.
JSTracer.startTracing({
  // If you want to log a custom string before each trace
  prefix: "[my log]",

  // Only if you want to restrict to a specific global,
  // otherwise it will trace the current global automatically.
  global: window,

  // If you are about to call code from another global(s),
  // this will trace code from all active globals in the current thread.
  // (use only if needed)
  traceAllGlobals: true,

  // Only if you want to step within function execution (this adds lots of additional traces!)
  traceSteps: true,

  // If you want to restrict traces to one JS file
  filterFrameSourceUrl: "foo.js",

  // If you want to avoid logging nested trace above a given threshold
  maxDepth: 10,

  // If you want the tracer to automatically stop after having logged a given amount of traces
  maxRecords: 10,

  // If you want to log all DOM events fired on the traced global(s)
  traceDOMEvents: true,

  // If you want to log all DOM Mutations happening in the traced global(s)
  traceDOMMutations: ["add", "attributes", "delete"],
});

[...run some JS code...]

JSTracer.stopTracing();