2010-05-19 205 views
125

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

+7

我刚写过一个规范的答案,它解决了所有*浏览器中浏览器扩展的单元测试和集成测试问题,而不仅仅是Chrome。请参阅[对“测试浏览器扩展”的答案](http://stackoverflow.com/a/17370531/938089)。 – 2013-06-28 21:52:06

回答

93

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

在最近的过去,我已经把那个被嵌入到应用程序,但无法到达,除非身体类型“测试”页面上我的所有测试。

举例来说,我会在访问一个页面中的所有测试下chrome-extension://asdasdasdasdad/unittests.html

测试将有机会获得localStorage等用于访问内容的脚本,在理论上可以测试,通过测试页的IFRAME嵌入但是,这些是更多的集成级别测试,单元测试会要求您将其从实际页面抽象出来,以便您不依赖它们,同样可以访问localStorage。

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

至于框架,JsUnit或更近Jasmine应该正常工作

+1

你是对的,测试真实页面不属于单元测试。我应该提出更广泛的问题。但它仍然是我想测试的东西,尤其是因为网站的html结构可能会随时更改。我修改了这个问题。 – swampsjohn 2010-05-24 19:39:02

+1

我会通过单元测试页面中的IFrame进行测试。内容脚本应该仍然会触发(如果您启用脚本以在iFrame中运行) – Kinlan 2010-05-24 19:55:44

+2

代理示例扩展有一些测试,它们只是模拟必需的Chrome API的各个部分:http://code.google。 com/chrome/extensions/samples.html#chrome.proxy ..同样我们的同事Boris使用QUnit来测试他的“模型”层:https://github.com/borismus/Question-Monitor-for-Stack-Exchange/树/主/测试 – 2012-01-17 20:27:32

2

关于在Chrome中已经存在的工具:。

  1. 在c hrome开发人员工具,有资源的部分用于本地存储。

    开发工具>资源>本地存储

    见的localStorage那里的变化。

  2. 您可以使用console.profile来测试性能并监视运行时调用堆栈。

  3. 的文件系统,您可以使用此URL来检查您的文件上传,编辑或不: 文件系统:铬扩展:///临时/

如果您是使用内容脚本和本地存储没有后台页面/脚本和没有消息传递的情况下,只能从该站点访问本地存储。 因此,要测试这些页面,您必须在这些选项卡中插入测试脚本。

+1

没有为我工作,但它确实让我进一步沿着我的JavaScript。 +1。 – mobibob 2014-04-20 02:24:18

+0

对于fileSystem您可以使用: 文件系统:chrome-extension:// /temporary/ – 2014-04-20 04:35:25

47

工作几个扩展我想出了sinon-chrome项目,允许使用mocha,nodejsphantomjs运行单元测试。

Basicaly,它创建所有chrome.* api的sinon mocks,您可以在其中放置任何预定义的json响应。

接下来,使用节点的vm.runInNewContext作为背景页面,使用phantomjs作为渲染弹出窗口/选项页面加载脚本。

最后,你断言chrome api被调用了所需的参数。

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

背景页:

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

为了测试它,我们需要:

  1. 模拟chrome.tabs.query返回预定义的响应,例如两个选项卡。 。
  2. 注入我们的嘲笑铬* API到一些环境
  3. 运行我们的扩展代码在这种环境下
  4. 断言,胸章等于“2”

的代码片段是以下几点:

var vm = require('vm'); 
var fs = require('fs'); 
var 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 
var context = { 
    chrome: chrome; 
}; 

// 3. run our extension code in this environment 
var 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" 
}); 

现在,我们可以把它包装成摩卡的describe..it功能,从终端上运行

$ mocha 

background page 
    ✓ should display opened tabs count in button badge 

1 passing (98ms) 

你可以找到完整的例子here

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

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

听起来不错 - 我一定会给它一个旋转! – jakabadambalazs 2015-02-07 16:49:58

+0

这个例子的链接似乎已经死了 - 你能否更新它? – Raisen 2015-12-07 20:55:33

+0

更新了示例链接。此外,sinon-chrome现在已移至https://github.com/acvetkov,并且很快就会有新的例子 – vitalets 2015-12-10 14:13:58

0

虽然sinon.js似乎工作的伟大,你也可以只使用普通的茉莉花和嘲笑你需要安装Chrome回调。例如:

Mock

chrome = { 
    runtime: { 
    onMessage : { 
     addListener : function() {} 
    } 
    } 
} 

Test

describe("JSGuardian", function() { 

    describe("BlockCache", function() { 

    beforeEach(function() { 
     this.blockCache = new BlockCache(); 
    }); 

    it("should recognize added urls", function() { 
     this.blockCache.add("http://some.url"); 
     expect(this.blockCache.allow("http://some.url")).toBe(false); 
    }); 
} // ... etc 

只需修改默认SpecRunner.html来运行代码。