É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 personnes savent comment procéder dans notre base de code Rails avec rspec, mais le côté JavaScript peut parfois sembler mystérieux.

Heureusement, il est aujourd’hui assez simple 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 en fondu. Écrivons un test pour celui-ci. 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 exécutera alors les tests de composants et affichera quelque chose comme « 2 assertions sur 2 passées, 0 échec ».

Notez que sur la page /qunit, vous pouvez exécuter d’autres tests. Il vous suffit de sélectionner un nouveau test dans le menu déroulant Module en haut de l’écran.

Analysons le test pour comprendre son fonctionnement.

La ligne template indique à Ember comment nous souhaitons insérer notre composant. Il s’agit exactement du même code que vous utiliseriez pour placer le composant dans un modèle Handlebars, vous devriez donc être familier :

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

Notez que testSnack est transmis en tant que paramètre snack. Cela est défini dans la méthode setup() :

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

J’ai simplement ajouté des données factices. C’est tout ce dont nous avons besoin pour que 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 utilisent ce sélecteur pour récupérer la valeur du titre de la collation et de sa description, puis les comparent à ce que nous attendons. Si les valeurs correspondent, les assertions passent et notre test fonctionne correctement.

Il est important de noter que vous n’avez pas besoin de tester chaque petit détail d’un composant comme celui-ci. Faites preuve de discernement et essayez de déterminer quels éléments de votre code sont susceptibles de poser problème ou de créer de la confusion pour d’autres développeurs à l’avenir. Si vous testez trop de choses dans votre modèle, cela rendra la modification du code plus difficile pour quelqu’un d’autre à l’avenir. Commencez simplement par tester les éléments les plus évidents, et avec le temps, vous prendrez le coup de main.

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 le ferait dans son navigateur. Je commence souvent par des tests d’acceptation, puis, si je crée un composant complexe, j’ajoute également des tests spécifiques pour celui-ci.

Voici comment nous pouvons écrire un test d’acceptation qui visitera notre route /admin/snack et confirmera que la collation a bien é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 ressemble presque à de l’anglais ! La première commande indique de visiter l’URL /admin/snack. Ensuite, 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. Comme le code JavaScript et Ember est asynchrone, nous devons nous assurer qu’Ember a terminé toutes ses tâches avant l’exécution de nos assertions. Enfin, il vérifie 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 échouera 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 effectue une requête AJAX pour récupérer ses données. Le test d’acceptation a exécuté le côté JavaScript, mais il ne savait pas comment récupérer les données depuis Rails.

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

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

Juste en dessous, ajoutez une ligne pour retourner un objet collation factice que notre test d’acceptation pourra utiliser :

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

Vous pouvez lire le code ci-dessus comme suit : « pour toute requête vers /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 pouvez essayer de développer une petite fonctionnalité et d’ajouter des tests pour vous assurer qu’elle fonctionne. Vous pouvez même essayer d’utiliser le TDD (développement piloté par les tests) en créant vos tests avant d’écrire du code côté interface utilisateur. Selon ce sur quoi vous travaillez et vos préférences personnelles, vous pourriez trouver cela plus agréable. Bonne chance et bon codage :slight_smile:


Ce document est versionné - proposez 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 »