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

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

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

使用浏览器测试库

多种测试库均支持扩展。

媒体库 指南
Puppeteer / Playwright 请参阅 Chrome 扩展程序 (Puppeteer / Playwright)。
使用 ChromeOptions 对象加载扩展程序。如需了解详情,请点击此处
WebDriverIO 请参阅网页扩展程序测试

在无头 Chrome 中运行测试

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

设置扩展程序 ID

在测试中,通常需要使用固定的扩展程序 ID。这使得许多常见任务变得更加轻松,例如在需要通信的服务器上将扩展程序的来源列入许可名单,或在测试中打开扩展程序页面。为此,请按照保持扩展程序 ID 不变中的步骤操作。

测试扩展程序页面

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

测试扩展程序弹出式窗口

使用某些库时,您或许可以使用 action.openPopup() API 打开弹出式窗口,然后获取对新上下文的引用。例如,Puppeteer 在其 Chrome 扩展程序指南中介绍了如何执行此操作。

如果您选择的库不支持此操作,请在新标签页中打开弹出式窗口的网址。如果您的弹出式窗口使用有效标签页,请考虑实现一种替换方法,以便将标签页 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 await chrome.tabs.get(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 终止,请参阅使用 Puppeteer 测试 Service Worker 终止。我们还提供了 Puppeteer 和 Selenium 的示例

请注意,使用某些测试框架时,服务工作线程可能不会像正常使用时那样自动终止。在 Selenium 中,情况就是如此。它依赖于 ChromeDriver,后者会将调试器附加到所有服务工作线程,从而防止这些线程被停止。