Écrire des tests d'acceptation et des tests de composants pour le code Ember dans Discourse

Les tests automatisés sont un excellent moyen de protéger votre code contre les régressions futures. Beaucoup de gens savent comment faire cela dans notre base de code Rails avec rspec, mais le côté Javascript peut être une sorte d’énigme pour certains.

Heureusement, il est assez facile de nos jours d’ajouter des tests de base à votre code Ember !

Tests de Composants

Dans le tutoriel précédent de cette série, nous avons ajouté un composant appelé fancy-snack pour afficher notre collation avec un arrière-plan dégradé. Écrivons un test pour cela. Créez le fichier suivant :

test/javascripts/components/snack-test.js

import componentTest from "helpers/component-test";

moduleForComponent("fancy-snack", { integration: true });

componentTest("test the rendering", {
  template: "{{fancy-snack snack=testSnack}}",

  setup() {
    this.set("testSnack", {
      name: "Potato Chips",
      description: "Now with extra trans fat!",
    });
  },

  test(assert) {
    assert.equal(this.$(".fancy-snack-title h1").text(), "Potato Chips");
    assert.equal(
      this.$(".fancy-snack-description p").text(),
      "Now with extra trans fat!"
    );
  },
});

Pour exécuter le test, ouvrez votre navigateur sur votre serveur de développement à l’adresse /qunit?module=component%3Afancy-snack. Votre navigateur effectuera alors les tests du composant et affichera quelque chose comme « 2 assertions sur 2 passées, 0 échouées. »

Notez que lorsque vous êtes sur la page /qunit, vous pouvez exécuter d’autres tests. Vous pouvez simplement sélectionner un nouveau test dans la liste déroulante Module en haut de l’écran.

Décortiquons le test pour comprendre son fonctionnement.

La ligne template indique à Ember comment nous souhaitons insérer notre composant. C’est exactement le même balisage que vous utiliseriez pour placer le composant dans un modèle handlebars, il devrait donc vous être familier :

template: '{{fancy-snack snack=testSnack}}',

Notez qu’il transmet testSnack comme paramètre snack. Ceci est défini dans la méthode setup() :

setup() {
  this.set('testSnack', {
    name: 'Potato Chips',
    description: 'Now with extra trans fat!'
  });
},

J’ai juste mis des données factices. C’est tout ce que nous avons besoin de faire pour qu’Ember rende le composant. Enfin, nous avons quelques assertions dans la méthode test() :

test(assert) {
  assert.equal(this.$('.fancy-snack-title h1').text(), 'Potato Chips');
  assert.equal(this.$('.fancy-snack-description p').text(), 'Now with extra trans fat!');
}

Si vous utilisez this.$(), vous avez accès à un sélecteur jQuery dans votre modèle. Les assertions ici utilisent ce sélecteur pour récupérer la valeur du titre de la collation et de la description de la collation et les comparer à ce que nous attendons. Si les valeurs correspondent, les assertions passeront et notre test fonctionnera.

Il est à noter que vous n’avez pas besoin de tester chaque petite chose dans un composant comme celui-ci. Vous devez faire preuve de discernement et essayer de déterminer ce qui, dans votre code, est susceptible de casser ou de prêter à confusion pour d’autres développeurs par la suite. Si vous testez trop de choses dans votre modèle, cela rendra la modification difficile pour quelqu’un d’autre à l’avenir. Commencez petit, testez les choses les plus évidentes, et avec le temps, vous vous y habituerez.

Tests d’Acceptation

Les tests d’acceptation sont souvent plus faciles à écrire et peuvent être plus puissants que les tests de composants car ils testent votre application de la même manière qu’un utilisateur dans son navigateur. Je commence souvent par des tests d’acceptation, puis si je crée un composant compliqué, j’ajoute également des tests pour celui-ci.

Voici comment nous pouvons écrire un test d’acceptation qui visitera notre route /admin/snack et confirmera que la collation a été rendue :

test/javascripts/acceptance/snack-test.js

import { acceptance } from "helpers/qunit-helpers";
acceptance("Snack");

test("Visit Page", function (assert) {
  visit("/admin/snack");
  andThen(() => {
    assert.ok(exists(".fancy-snack-title"), "the snack title is present");
  });
});

Le test() dans ce cas se lit presque comme de l’anglais ! La première commande demande de visiter l’URL /admin/snack. Après cela, il y a une méthode andThen(). Cette méthode est nécessaire pour s’assurer que tout le travail en arrière-plan est terminé avant que les tests ne continuent. Puisque le Javascript et le code Ember sont asynchrones, nous devons nous assurer qu’Ember a terminé tout ce qu’il doit faire avant que nos assertions ne soient exécutées. Enfin, il teste si l’élément .fancy-snack-title est présent.

Cependant, si vous exécutez ce test en visitant /qunit?module=Acceptance%3A%20Snack, vous constaterez que le test échoue, en raison d’une erreur AJAX.

Si vous vous en souvenez, notre code comprend à la fois un côté Rails et un côté Javascript qui effectuaient une requête AJAX pour obtenir ses données. Le test d’acceptation a exécuté le côté Javascript, mais il ne savait pas quoi faire pour obtenir ses données de Rails.

Pour corriger cela, nous devons ajouter une fausse réponse, en utilisant l’excellente bibliothèque pretender. Ouvrez le fichier test/javascripts/helpers/create-pretender.js et recherchez la ligne qui dit :

this.get("/admin/plugins", () => response({ plugins: [] }));

Juste en dessous, ajoutez une ligne pour retourner un faux objet collation pour que notre test d’acceptation fonctionne :

this.get("/admin/snack.json", () => {
  return response({ name: "snack name", description: "snack description" });
});

Vous pouvez lire le code ci-dessus comme « pour toute requête à /admin/snack.json, répondez avec la response suivante. »

Si vous actualisez l’URL /qunit?module=Acceptance%3A%20Snack, votre test d’acceptation devrait récupérer ses données via pretender et les tests devraient passer.

Où aller à partir d’ici

Vous pourriez essayer de développer une petite fonctionnalité et d’ajouter des tests pour vous assurer qu’elle fonctionne. Vous pourriez même essayer d’utiliser le TDD en créant vos tests avant d’écrire du code sur le front-end. En fonction de ce sur quoi vous travaillez et de vos préférences personnelles, vous pourriez trouver que c’est une façon plus agréable de procéder. Bonne chance et bon codage :slight_smile:


Ce document est contrôlé par version - suggérez des modifications sur github.

15 « J'aime »

My prior experience in writing qunit tests was based on the other howto

i.e. “acceptance” was simply

acceptance("Purple Tentacle", { loggedIn: true });

I have seen in other plugins where the test code contained “fake” JSON to test against. I wasn’t sure if that would be as good as testing against “real” data, so I wanted to avoid doing it that way.

The six tests passed, but I got a couple of rather angry looking “unhandled request” errors.

After finding an example of some “setup” code, I tried it and it solved the errors.

It works, but I’m not really sure why, nor why it’s needed for some but not for the majority of plugins I’ve seen that have qunit tests.

3 « J'aime »

For a long time we weren’t great with testing plugins, so not many people followed our example and added tests.

You are right to add a response using pretender to handle AJAX calls.

4 « J'aime »

Juste une note que le chemin /qunit est obsolète. C’est maintenant /tests. Il m’a fallu un certain temps pour le comprendre :slight_smile:

1 « J'aime »