【问题标题】:How do I test Chrome Extension/Firefox WebExtension code?如何测试 Chrome 扩展/Firefox WebExtension 代码?
【发布时间】:2017-12-31 16:16:38
【问题描述】:

由于 Firefox 强迫我这样做,我正在重写我的扩展程序以使用 WebExtension API,即 Chrome 的扩展 API。我想进行自动化测试。到目前为止,我已经尝试过:

我有一个package.json,以便npm 安装依赖项:

{
  "name": "extension-api-tests",
  "version": "0.0.1",
  "scripts": {
    "test": "karma start"
  },
  "devDependencies": {
    "karma": "^1.3.0",
    "karma-firefox-launcher": "^1.0.0",
    "karma-mocha": "^1.3.0",
    "karma-sinon-chrome": "^0.2.0",
    "mocha": "^3.1.2",
    "sinon-chrome": "^2.1.2"
  }
}

我有一个 karma.conf.js 来设置该测试运行器:

module.exports = function(config) {
  config.set({
    frameworks: ['mocha', 'sinon-chrome'],
    files: ['test.js'],
    reporters: ['dots'],
    autoWatch: false,
    browsers: ['Firefox'],
    singleRun: true,
    concurrency: Infinity,
  });
};

我已经完成了基本测试:

describe('my frustration', () => {
  it('works when it uses no APIs', done => {
    done();
  });

  it('should respond to messages!', done => {
    console.log('message test starting');
    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      console.log('received message');
      sendResponse(true);
    });
    chrome.runtime.sendMessage({}, result => {
      console.log('received response to message');
      done();
    });
  });

  it('should open a tab!', done => {
    console.log('tab test starting');
    chrome.tabs.create({
      'active': true,
      'url': 'http://www.example.com/',
    }, tab => {
      console.log('created a tab:', tab);
      done();
    });
  });
});

这当然是一个简化的测试用例。当我运行npm test 时,我得到(略略):

> extension-api-tests@0.0.1 test .../ext-test
> karma start

25 07 2017 11:57:10.395:INFO [karma]: Karma v1.7.0 server started at http://0.0.0.0:9876/
25 07 2017 11:57:10.397:INFO [launcher]: Launching browser Firefox with unlimited concurrency
25 07 2017 11:57:10.404:INFO [launcher]: Starting browser Firefox
25 07 2017 11:57:14.687:INFO [Firefox 54.0.0 (Ubuntu 0.0.0)]: Connected on socket iIjNRRQfzWj68_GNAAAA with id 42440302
.
LOG: 'message test starting'
Firefox 54.0.0 (Ubuntu 0.0.0) my frustration should respond to messages! FAILED
        Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
LOG: 'tab test starting'
Firefox 54.0.0 (Ubuntu 0.0.0) my frustration should open a tab! FAILED
        Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Firefox 54.0.0 (Ubuntu 0.0.0): Executed 3 of 3 (2 FAILED) (3.998 secs / 4.001 secs)
npm ERR! Test failed.  See above for more details.

我尝试使用扩展 API 的测试都失败了。它确实 not 说(例如)chrome.runtime 没有定义(但如果我从 karma.conf.js 中删除 'sinon-chrome' 就会这样做),所以我相信我已经设置了 sinon。但是 API 从不做任何事情,从不工作。我要测试的代码是所有关于通过这些 API 传递数据(尤其是作为消息,以跨越 chrome/content 边界)。

【问题讨论】:

  • 不能对主要问题发表评论,但是当你解决它时,请注意 runtime.sendMessage 自 Chrome 49 以来并显然在所有版本的 Firefox 中都不会发送到自己的页面/框架。
  • 猜测 sinon 提供了一个与真实 API 不太一样的假冒产品,以使测试成为可能。
  • 确实,sinon 文档中的示例与您使用的直接调用完全不同。我不知道 sinon,所以不能说这是否是唯一支持的方法。
  • 尝试在问题中添加 sinon 标签,以便 sinon 专家可以看到。
  • 您(已删除)的答案有助于解释您的具体问题。

标签: testing google-chrome-extension sinon firefox-addon-webextensions


【解决方案1】:

根据https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/sendMessage sendMessage 返回一个Promise。根据您的日志,您在

中的成功处理程序
chrome.runtime.sendMessage({}, result => {
  console.log('received response to message');
  done();
});

与运行测试的主线程相比,没有及时调用。您应该尝试向主线程添加睡眠

function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

像这样

chrome.runtime.sendMessage({}, result => {
  console.log('received response to message');
});

sleep(500).then(() => {
  done();
});

只要 sendMessage 在 500 毫秒内返回,这应该可以工作。

【讨论】:

    【解决方案2】:

    除了原始问题中的所有设置外,请注意 Sinon 仅提供 API 表面的存根/模拟:不是假 API 实现。

    为了让测试“工作”,还必须声明模拟的行为;参见例如https://sinonjs.org/releases/latest/mocks/https://sinonjs.org/releases/latest/stubs/ 。原始问题中的那种测试是“不可能的”,因为您主要是在测试您还需要在测试中编写的假实现。

    一旦设置了 sinon-chrome,你就可以编写更像

    的测试了
    chrome.tabs.executeScript.callsArg(2);
    // ... call code under test ...    
    assert(chrome.tabs.executeScript.calledOnce);
    

    (这不是我真正想要编写的那种测试。)

    【讨论】:

    • 你使用真正的browser-/w​​ebextension api有没有成功?
    • 不,我调整了测试策略。
    猜你喜欢
    • 2010-11-25
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多