Как проверить расширения Chrome?

154

Есть ли хороший способ сделать это? Я пишу расширение, которое взаимодействует с веб-сайтом в виде скрипта контента и сохраняет данные с помощью localalstorage. Существуют ли какие-либо инструменты, платформы и т. Д., Которые я могу использовать для проверки этого поведения? Я понимаю, что есть несколько общих инструментов для тестирования javascript, но достаточно ли они для тестирования расширения? Модульное тестирование является наиболее важным, но я также заинтересован в других типах тестирования (таких как интеграционное тестирование).

swampsjohn
источник
8
Я только что написал канонический ответ, в котором рассматриваются модульное тестирование и интеграционное тестирование расширений браузера для всех браузеров, а не только для Chrome. Смотрите ответ на "Тестирование расширений браузера" .
Роб W

Ответы:

111

Да, существующие фреймворки довольно полезны ..

В недавнем прошлом я разместил все свои тесты на «тестовой» странице, которая была встроена в приложение, но недоступна, если не набрана физически.

Например, у меня были бы все тесты на странице, доступной в chrome-extension://asdasdasdasdad/unittests.html

Тесты будут иметь доступ к localStorage т. Д. Для доступа к сценариям содержимого теоретически вы можете проверить это с помощью встроенных IFRAME на своей тестовой странице, однако это больше тестирование уровня интеграции, модульные тесты потребуют от вас абстрагироваться от реальных страниц, чтобы вы могли не зависит от них, также с доступом к localStorage.

Если вы хотите протестировать страницы напрямую, вы можете организовать свое расширение для открытия новых вкладок (chrome.tab.create ({"url": "someurl"}). Для каждой из новых вкладок должен работать скрипт содержимого, и вы можете использовать ваш тестовый фреймворк для проверки того, что ваш код сделал то, что должен.

Что касается фреймворков, JsUnit или более поздний Jasmine должны работать нормально.

Kinlan
источник
1
Вы правы, тестирование реальных страниц не попадает под юнит-тестирование. Я должен был сделать мой вопрос более широким. Но это все еще то, что я хотел бы проверить, тем более что структура html сайта может измениться в любое время. Я изменил вопрос.
swampsjohn
1
Я бы по-прежнему тестировал IFrames на вашей странице тестового модуля. Скрипты контента должны все еще запускаться (если вы включите скрипты для запуска в iFrame)
Kinlan
3
У примера расширения прокси есть несколько тестов, которые просто макетируют кусочки API Chrome, которые были необходимы: code.google.com/chrome/extensions/samples.html#chrome.proxy .. Также наш коллега Борис использовал для тестирования QUnit его «модельный» слой: github.com/borismus/Question-Monitor-for-Stack-Exchange/tree/…
Пол Ирландский
63

Работая над несколькими расширениями Chrome, я придумал sinon-chromeпроект, который позволяет запускать юнит-тесты с использованием mocha, nodejsи phantomjs.

По сути, он создает макеты sinon для всех chrome.*API, в которые вы можете поместить любые предопределенные ответы json.

Затем вы загружаете свои скрипты, используя узлы vm.runInNewContextдля фоновой страницы иphantomjs для всплывающих окон / опций рендера.

И, наконец, вы утверждаете, что Chrome API был вызван с необходимыми аргументами.

Давайте рассмотрим пример.
Предположим, у нас есть простое расширение Chrome, которое отображает количество открытых вкладок в значке кнопки.

фоновая страница:

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

Чтобы проверить это нам нужно:

  1. макет chrome.tabs.queryдля возврата предварительно определенного ответа, например, две вкладки.
  2. впрыснуть наш глумленный chrome.*API в какую-то среду
  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"
});

Теперь мы можем обернуть его в 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'});
vitalets
источник
Ссылка на пример кажется мертвой - не могли бы вы обновить ее?
Raisen
1
Обновлена ​​ссылка на пример. Также sinon-chrome теперь перенесен на github.com/acvetkov, и скоро появятся новые примеры
vitalets
3

В то время как, sinon.jsкажется, прекрасно работает, вы также можете просто использовать простой жасмин и высмеивать необходимые обратные вызовы Chrome. Пример:

издеваться

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

Тест

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по умолчанию для запуска вашего кода.

Serv-вкл
источник
2

О уже существующем инструменте в Chrome:

  1. В инструменте разработчика Chrome есть раздел Ресурсы для локального хранилища.

    Инструменты разработчика> Ресурсы> Локальное хранилище

    Смотрите изменения местного хранилища там.

  2. Вы можете использовать console.profile для тестирования производительности и просмотра стека вызовов во время выполнения.

  3. для файловой системы Вы можете использовать этот URL, чтобы проверить, загружен файл или нет: файловая система: расширение chrome: /// временный /

Если вы используете скрипт контента и локальное хранилище вместе без фоновой страницы / скрипта и без передачи сообщений, локальное хранилище будет доступно только с этого сайта. Таким образом, чтобы протестировать эти страницы, вы должны вставить свой тестовый скрипт в эти вкладки.

Нафис Ахмад
источник
1
Это не сработало для меня, но это помогло мне продвинуться дальше в моем JavaScript. +1 за это.
Мобибоб
Для файловой системы Вы можете использовать: файловую систему: расширение chrome: // <идентификатор-yourextension> / временный /
Нафис Ахмад
1

Я обнаружил, что могу использовать веб-драйвер Selenium для запуска свежего экземпляра браузера с предустановленным расширением и pyautogui для кликов - потому что Selenium не может управлять «просмотром» расширения. После кликов вы можете делать скриншоты и сравнивать их с «ожидаемыми», ожидая 95% сходства (потому что в разных браузерах допустимы перемещения разметки до нескольких пикселей).

Виталий Зданевич
источник
0

Чтобы подтвердить пару предыдущих ответов, Jasmine хорошо работает с расширениями Chrome. Я использую версию 3.4.0.

Вы можете использовать шпионов Jasmine, чтобы легко создавать двойники теста для различных API. Не нужно строить свой собственный с нуля. Например:

describe("Test suite", function() {

  it("Test case", function() {

    // Set up spies and fake data.
    spyOn(chrome.browserAction, "setPopup");
    spyOn(chrome.identity, "removeCachedAuthToken");
    fakeToken = "faketoken-faketoken-faketoken";
    fakeWindow = jasmine.createSpyObj("window", ["close"]);

    // Call the function under test.
    logout(fakeWindow, fakeToken);

    // Perform assertions.
    expect(chrome.browserAction.setPopup).toHaveBeenCalledWith({popup: ""});
    expect(chrome.identity.removeCachedAuthToken).toHaveBeenCalledWith({token: fakeToken});
    expect(fakeWindow.close.calls.count()).toEqual(1);

  });

});

Еще немного подробностей, если это поможет:

Как упоминалось в другом ответе, я создал HTML-страницу как часть моего расширения браузера, которое запускает мои тесты. HTML-страница содержит библиотеку Jasmine, а также код JavaScript моего расширения и мой набор тестов. Тесты запускаются автоматически и результаты форматируются для вас. Нет необходимости создавать тестовый прогон или форматировщик результатов. Просто следуйте инструкциям по установке и используйте документ, задокументированный в HTML, для создания своей страницы для запуска теста, а также включите в нее свой набор тестов.

Я не думаю, что вы можете динамически получать фреймворк Jasmine с другого хоста, поэтому я просто включил релиз Jasmine в свое расширение. Я опущу это, а также мои тестовые случаи, когда я, конечно, соберу свое расширение для производства.

Я не смотрел, как выполнять свои тесты в командной строке. Это было бы удобно для инструментов автоматического развертывания.

Джон А
источник