如何测试Chrome扩展程序?

有没有一个好方法可以做到这一点?我正在编写一个扩展,该扩展以内容脚本的形式与网站交互,并使用本地存储保存数据。是否有任何工具、框架等可用于测试此行为?我意识到有一些通用工具可以测试javascript,但是这些工具是否足以测试扩展?单元测试是最重要的,但我也对其他类型的测试(如集成测试)感兴趣。


答案 1

是的,现有的框架非常有用。

在最近的过去,我已将所有测试放在嵌入到应用程序中的“测试”页面上,但除非以物理方式键入,否则无法访问该页面。

例如,我会在页面下访问所有测试chrome-extension://asdasdasdasdad/unittests.html

测试将可以访问等。对于访问内容脚本,从理论上讲,您可以通过测试页面中的嵌入式IFRAME对其进行测试,但是这些是更多的集成级测试,单元测试将要求您将其从真实页面中抽象出来,以便您不依赖于它们,同样可以访问localStorage。localStorage

如果你想直接测试页面,你可以编排你的扩展来打开新标签页(chrome.tab.create({“url” : “someurl”})。对于内容脚本应运行的每个新选项卡,您可以使用测试框架来检查代码是否完成了它应该执行的操作。

至于框架,JsUnit或最近的Jasmine应该可以正常工作。


答案 2

在几个chrome扩展上,我想出了sinon-chrome项目,它允许使用,和运行单元测试。mochanodejsphantomjs

基本上,它创建了所有API的sinon模拟,您可以在其中放置任何预定义的json响应。chrome.*

接下来,使用节点的后台页面和渲染弹出窗口/选项页面加载脚本。vm.runInNewContextphantomjs

最后,您断言chrome api是使用所需的参数调用的。

让我们举个例子:
假设我们有一个简单的chrome扩展程序,它在按钮徽章中显示打开的标签页的数量。

背景页面:

chrome.tabs.query({}, function(tabs) {
  chrome.browserAction.setBadgeText({text: String(tabs.length)});
});

为了测试它,我们需要:

  1. mock 返回预定义的响应,例如两个选项卡。chrome.tabs.query
  2. 将我们模拟的 API 注入到某个环境中chrome.*
  3. 在此环境中运行我们的扩展代码
  4. 断言按钮徽章等于“2”

代码片段如下:

const vm = require('vm');
const fs = require('fs');
const chrome = require('sinon-chrome');

// 1. mock `chrome.tabs.query` to return predefined response 
chrome.tabs.query.yields([
  {id: 1, title: 'Tab 1'}, 
  {id: 2, title: 'Tab 2'}
]);

// 2. inject our mocked chrome.* api into some environment
const context = {
  chrome: chrome
};

// 3. run our extension code in this environment
const code = fs.readFileSync('src/background.js');
vm.runInNewContext(code, context);

// 4. assert that button badge equals to '2'
sinon.assert.calledOnce(chrome.browserAction.setBadgeText);
sinon.assert.calledWithMatch(chrome.browserAction.setBadgeText, {
  text: "2"
});

现在我们可以将其包装到mocha的函数中并从终端运行:describe..it

$ mocha

background page
  ✓ should display opened tabs count in button badge

1 passing (98ms)

您可以在此处找到完整的示例。

此外,sinon-chrome允许使用预定义的响应触发任何chrome事件,例如

chrome.tab.onCreated.trigger({url: 'http://google.com'});