针对 Chrome 扩展程序的端到端测试

端到端测试涉及构建扩展程序软件包并将其加载到浏览器中。测试工具会与浏览器通信,以自动执行互动并测试用户将经历的相同流程。支持端到端测试的库通常会提供一些方法来控制浏览器、模拟用户输入和观察任何已打开页面的当前状态。

有关教程,请参阅使用 Puppeteer 测试 Chrome 扩展程序;如需详细了解如何为 Chrome 扩展程序编写单元测试,请参阅单元测试

使用浏览器测试库

一系列测试库都支持扩展程序。

媒体库 指导方针
木偶操作员 / 剧作家 查看 Chrome 扩展程序 (Puppeteer / Playwright)。
使用 ChromeOptions 对象加载扩展程序。如需了解详情,请点击此处
WebDriverIO 请参阅 Web 扩展程序测试

在无头 Chrome 中运行测试

在自动化工作流中运行测试时,通常需要在没有屏幕的计算机上加载扩展程序。Chrome 的新的无头模式允许 Chrome 像这样在无人值守的环境中运行。使用 --headless=new 标志启动 Chrome(无头浏览器目前默认为“old”,它不支持加载扩展程序)。根据您选择的自动化工具,可能会有一项设置自动为您添加该标志。

设置扩展程序 ID

通常建议在测试中使用固定的扩展程序 ID。这样可以简化许多常见任务,例如在需要与之通信的服务器上将扩展程序的来源列入许可名单,或在测试中打开扩展程序页面。为此,请按照保持一致的扩展程序 ID 中的步骤操作。

测试扩展程序页面

扩展程序页面可通过相应的网址(例如 chrome-extension://<id>/index.html)进行访问。使用所选自动化工具中提供的常规导航方法导航到这些网址。

测试扩展程序弹出式窗口

目前无法在其他页面的上下文中打开扩展程序弹出式窗口。请改为在新标签页中打开弹出式窗口的网址。如果弹出式窗口使用活动标签页,请考虑实现替换,从而将标签页 ID 显式传递到弹出式窗口。例如:

const URL_PARAMS  = new URLSearchParams(window.location.search);

async function getActiveTab() {
  // Open popup.html?tab=5 to use tab ID 5, etc.
  if (URL_PARAMS.has("tab")) {
    return parseInt(URL_PARAMS.get("tab"));
  }

  const tabs = await chrome.tabs.query({
    active: true,
    currentWindow: true
  });

  return tabs[0];
}

检查扩展程序状态

为了避免在更改扩展程序的内部行为时测试失败,通常最佳做法是避免在集成测试中访问内部状态。您应根据用户可见的内容进行测试。不过,有时您可能希望直接从扩展程序访问数据。在这种情况下,请考虑在扩展程序页面的上下文中执行代码。

在 Puppeteer 中:

const workerTarget = await browser.waitForTarget(
  target => target.type() === 'service_worker'
);
const worker = await workerTarget.worker();

const value = await worker.evaluate(() => {
  chrome.storage.local.get('foo');
});

在 Selenium 中:

// Selenium doesn't allow us to access the service worker, so we need to open an extension page where we can execute the code
await driver.get('chrome-extension://<id>/popup.html');
await driver.executeAsyncScript(
  'const callback = arguments[arguments.length - 1];' +
  'chrome.storage.local.get(\'foo\').then(callback);'
);

测试 Service Worker 的终止

如需了解如何测试 Service Worker 的终止,请参阅使用 Puppeteer 测试 Service Worker 的终止情况。我们还提供了 Puppeteer 和 Selenium 的示例

请注意,在使用某些测试框架时,Service Worker 可能不会像正常使用情况下一样自动终止。Selenium 中就是如此。它依赖于 ChromeDriver,而 ChromeDriver 会将调试程序连接到所有 Service Worker,从而防止它们被停止。