Comment tester les extensions Chrome?

154

Y at-il un bon moyen de le faire? J'écris une extension qui interagit avec un site Web en tant que script de contenu et enregistre les données à l'aide du stockage local. Existe-t-il des outils, des frameworks, etc. que je peux utiliser pour tester ce comportement? Je me rends compte qu'il existe des outils génériques pour tester javascript, mais sont-ils suffisamment puissants pour tester une extension? Les tests unitaires sont les plus importants, mais je suis également intéressé par d'autres types de tests (tels que les tests d'intégration).

swampsjohn
la source
8
Je viens d'écrire une réponse canonique qui traite des tests unitaires et des tests d'intégration pour les extensions de navigateur sur tous les navigateurs, pas seulement Chrome. Voir la réponse à "Test des extensions de navigateur" .
Rob W

Réponses:

111

Oui, les frameworks existants sont assez utiles.

Dans un passé récent, j'ai placé tous mes tests sur une page "test" qui était intégrée à l'application mais non accessible à moins d'être saisie physiquement.

Par exemple, j'aurais tous les tests dans une page accessible sous chrome-extension://asdasdasdasdad/unittests.html

Les tests auraient accès à, localStorageetc. ne dépendez pas d'eux, de même avec l'accès à localStorage.

Si vous souhaitez tester des pages directement, vous pouvez orchestrer votre extension pour ouvrir de nouveaux onglets (chrome.tab.create ({"url": "someurl"}). Pour chacun des nouveaux onglets, votre script de contenu doit s'exécuter et vous pouvez utiliser votre cadre de test pour vérifier que votre code a fait ce qu'il devrait faire.

En ce qui concerne les frameworks, JsUnit ou le plus récent Jasmine devrait fonctionner correctement .

Kinlan
la source
1
Vous avez raison, tester de vraies pages ne relève pas du test unitaire. J'aurais dû élargir ma question. Mais c'est toujours quelque chose que j'aimerais tester, d'autant plus que la structure html du site Web peut changer à tout moment. J'ai modifié la question.
swampsjohn
1
Je testerais encore via IFrames dans votre page de test unitaire. Les scripts de contenu devraient toujours se déclencher (si vous activez les scripts pour s'exécuter dans l'iFrame)
Kinlan
3
L'exemple d'extension de proxy a quelques tests qui simulent simplement les éléments des API Chrome qui étaient nécessaires: code.google.com/chrome/extensions/samples.html#chrome.proxy .. Notre collègue Boris a également utilisé QUnit pour les tests sa couche "modèle": github.com/borismus/Question-Monitor-for-Stack-Exchange/tree
Paul Irish
63

En travaillant sur plusieurs extensions chrome, j'ai créé un sinon-chromeprojet qui permet d'exécuter des tests unitaires en utilisant mocha, nodejset phantomjs.

Fondamentalement, il crée sinon des simulations de toutes les chrome.*API où vous pouvez placer toutes les réponses json prédéfinies.

Ensuite, vous chargez vos scripts en utilisant les nœuds vm.runInNewContextpour la page d'arrière-plan et phantomjspour la page contextuelle / d'options de rendu.

Et enfin, vous affirmez que l'API chrome a été appelée avec les arguments nécessaires.

Prenons un exemple:
supposons que nous ayons une simple extension chrome qui affiche le nombre d'onglets ouverts dans le badge de bouton.

page de fond:

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

Pour le tester, nous avons besoin de:

  1. mock chrome.tabs.querypour renvoyer une réponse prédéfinie, par exemple deux onglets.
  2. injecter notre chrome.*API fictive dans un environnement
  3. exécutez notre code d'extension dans cet environnement
  4. affirmer que le badge du bouton équivaut à «2»

L'extrait de code est le suivant:

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"
});

Maintenant, nous pouvons l'envelopper dans les describe..itfonctions de mocha et l'exécuter à partir du terminal:

$ mocha

background page
  ✓ should display opened tabs count in button badge

1 passing (98ms)

Vous pouvez trouver un exemple complet ici .

De plus, sinon-chrome permet de déclencher n'importe quel événement chrome avec une réponse prédéfinie, par exemple

chrome.tab.onCreated.trigger({url: 'http://google.com'});
vitalets
la source
Le lien pour l'exemple semble être mort - pourriez-vous s'il vous plaît le mettre à jour?
Raisen
1
Lien vers l'exemple mis à jour. Sinon-chrome est maintenant déplacé vers github.com/acvetkov et il y aura bientôt de nouveaux exemples
vitalets
3

Bien que cela sinon.jssemble fonctionner très bien, vous pouvez également simplement utiliser Jasmine ordinaire et simuler les rappels Chrome dont vous avez besoin. Exemple:

Moquer

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

Tester

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

Modifiez simplement la valeur par défaut SpecRunner.htmlpour exécuter votre code.

serv-inc
la source
2

À propos de l'outil déjà existant dans Chrome:

  1. Dans l'outil de développement Chrome, il existe une section pour les ressources pour le stockage local.

    Outils de développement> Ressources> Stockage local

    Voir les changements de localstorage ici.

  2. Vous pouvez utiliser console.profile pour tester les performances et surveiller la pile d'appels d'exécution.

  3. pour fileSystem Vous pouvez utiliser cette URL pour vérifier que votre fichier est téléchargé ou non: système de fichiers: chrome-extension: /// temporaire /

Si vous utilisez le script de contenu et le stockage local ensemble sans page / script d'arrière-plan et sans passage de message, le stockage local ne sera accessible qu'à partir de ce site. Donc, pour tester ces pages, vous devez injecter votre script de test dans ces onglets.

Nafis Ahmad
la source
1
Cela n'a pas fonctionné pour moi, mais cela m'a fait avancer dans mon javascript. +1 pour ça.
mobibob
Pour fileSystem, vous pouvez utiliser: filesystem: chrome-extension: // <yourextension-id> / temporaire /
Nafis Ahmad
1

J'ai trouvé que je pouvais utiliser le pilote Web Selenium pour démarrer une nouvelle instance de navigateur avec une extension préinstallée et pyautogui pour les clics - car Selenium ne peut pas conduire la "vue" de l'extension. Après les clics, vous pouvez faire des captures d'écran et les comparer avec celles `` attendues '', en espérant 95% de similitude (car sur différents navigateurs, les mouvements de balisage sont acceptables à quelques pixels).

Vitaly Zdanevich
la source
0

Pour confirmer quelques réponses précédentes, Jasmine semble bien fonctionner avec les extensions Chrome. J'utilise la version 3.4.0.

Vous pouvez utiliser des espions Jasmine pour créer facilement des doubles de test pour les différentes API. Pas besoin de créer le vôtre à partir de zéro. Par exemple:

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);

  });

});

Quelques détails supplémentaires, si cela aide:

Comme mentionné dans une autre réponse, j'ai créé une page HTML dans le cadre de l'extension de mon navigateur qui exécute mes tests. La page HTML comprend la bibliothèque Jasmine, ainsi que le code JavaScript de mon extension, ainsi que ma suite de tests. Les tests sont exécutés automatiquement et les résultats sont formatés pour vous. Pas besoin de créer un testeur ou un formateur de résultats. Suivez simplement les instructions d'installation et utilisez le code HTML documenté ici pour créer votre page d'exécution de test, et incluez également votre suite de tests dans la page.

Je ne pense pas que vous puissiez récupérer le framework Jasmine dynamiquement à partir d'un autre hôte, donc j'ai juste inclus la version Jasmine dans mon extension. Je vais l'omettre ainsi que mes cas de test lorsque je construirai mon extension pour la production, bien sûr.

Je n'ai pas regardé comment exécuter mes tests en ligne de commande. Ce serait pratique pour les outils de déploiement automatisés.

Jon A
la source