Akzeptanztests und Komponententests für Ember-Code in Discourse schreiben

Automatisierte Tests sind eine hervorragende Möglichkeit, Ihren Code vor zukünftigen Regressionen zu schützen. Viele kennen die Vorgehensweise in unserer Rails-Codebase mit rspec, doch die JavaScript-Seite kann für einige etwas rätselhaft sein.

Glücklicherweise ist es heutzutage ziemlich einfach, grundlegende Tests zu Ihrem Ember-Code hinzuzufügen!

Komponententests

Im vorherigen Tutorial dieser Reihe haben wir eine Komponente namens fancy-snack hinzugefügt, um unseren Snack mit einem ausblendenden Hintergrund anzuzeigen. Schreiben wir nun einen Test dafür. Erstellen Sie die folgende Datei:

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

Um den Test auszuführen, öffnen Sie Ihren Browser auf Ihrem Entwicklungsserver unter /qunit?module=component%3Afancy-snack. Ihr Browser führt dann die Komponententests durch und gibt etwas wie „2 von 2 Assertions bestanden, 0 fehlgeschlagen“ aus.

Beachten Sie, dass Sie auf der /qunit-Seite auch andere Tests ausführen können. Wählen Sie einfach einen neuen Test aus dem Dropdown-Menü Module oben auf dem Bildschirm aus.

Lassen Sie uns den Test Schritt für Schritt durchgehen, um zu verstehen, wie er funktioniert.

Die Zeile template teilt Ember mit, wie wir unsere Komponente einfügen möchten. Es ist exakt dasselbe Markup, das Sie auch verwenden würden, um die Komponente in einer Handlebars-Vorlage zu platzieren, daher sollte es Ihnen vertraut sein:

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

Beachten Sie, dass testSnack als Parameter snack übergeben wird. Dies wird in der setup()-Methode definiert:

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

Ich habe einfach einige Dummy-Daten eingefügt. Das ist alles, was nötig ist, damit Ember die Komponente rendert. Schließlich haben wir im test()-Methodenaufruf ein paar Assertions:

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!');
}

Wenn Sie this.$() verwenden, erhalten Sie Zugriff auf einen jQuery-Selektor in Ihrer Vorlage. Die Assertions hier nutzen diesen Selektor, um den Wert des Snack-Titels und der Snack-Beschreibung zu extrahieren und mit dem Erwarteten zu vergleichen. Wenn die Werte übereinstimmen, bestehen die Assertions und unser Test funktioniert.

Es ist erwähnenswert, dass Sie nicht jedes kleine Detail in einer Komponente wie dieser testen müssen. Seien Sie umsichtig und versuchen Sie herauszufinden, welche Teile Ihres Codes wahrscheinlich brechen oder anderen Entwicklern in Zukunft Verwirrung stiften könnten. Wenn Sie zu viele Dinge in Ihrer Vorlage testen, wird es für andere in der Zukunft mühsam, Änderungen vorzunehmen. Fangen Sie einfach klein an, testen Sie die offensichtlichsten Dinge, und mit der Zeit werden Sie den Dreh raus haben.

Akzeptanztests

Akzeptanztests sind oft einfacher zu schreiben und können leistungsfähiger sein als Komponententests, da sie Ihre Anwendung so testen, wie ein Benutzer dies in seinem Browser tun würde. Ich beginne oft mit Akzeptanztests und füge dann, falls ich eine komplexe Komponente entwickle, auch Tests dafür hinzu.

So können wir einen Akzeptanztest schreiben, der unsere Route /admin/snack aufruft und bestätigt, dass der Snack gerendert wurde:

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

Das test()-Element liest sich in diesem Fall fast wie Englisch! Der erste Befehl sagt, dass die URL /admin/snack aufgerufen werden soll. Danach folgt eine andThen()-Methode. Diese Methode ist notwendig, um sicherzustellen, dass alle Hintergrundarbeiten abgeschlossen sind, bevor die Tests weiterlaufen. Da JavaScript- und Ember-Code asynchron sind, müssen wir sicherstellen, dass Ember alles erledigt hat, was nötig ist, bevor unsere Assertions ausgeführt werden. Schließlich wird geprüft, ob das Element .fancy-snack-title vorhanden ist.

Wenn Sie diesen Test jedoch ausführen, indem Sie /qunit?module=Acceptance%3A%20Snack aufrufen, werden Sie feststellen, dass der Test aufgrund eines AJAX-Fehlers fehlschlägt.

Wenn Sie sich erinnern, umfasst unser Code sowohl eine Rails-Seite als auch eine JavaScript-Seite, die eine AJAX-Anfrage stellt, um die Daten zu erhalten. Der Akzeptanztest führte die JavaScript-Seite aus, wusste aber nicht, wie er die Daten von Rails beziehen sollte.

Um dies zu beheben, müssen wir eine gefälschte Antwort hinzufügen, indem wir die hervorragende Bibliothek pretender verwenden. Öffnen Sie die Datei test/javascripts/helpers/create-pretender.js und suchen Sie nach der Zeile, die besagt:

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

Direkt darunter fügen Sie eine Zeile hinzu, um ein gefälschtes Snack-Objekt zurückzugeben, mit dem unser Akzeptanztest arbeiten kann:

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

Sie können den obigen Code so lesen: „Für jede Anfrage an /admin/snack.json antworte mit der folgenden response.“

Wenn Sie die URL /qunit?module=Acceptance%3A%20Snack aktualisieren, sollte Ihr Akzeptanztest seine Daten über pretender abrufen und die Tests sollten bestehen.

Wohin es von hier aus geht

Sie könnten versuchen, eine kleine Funktion zu entwickeln und Tests hinzuzufügen, um sicherzustellen, dass sie funktioniert. Sie könnten sogar versuchen, TDD zu verwenden, indem Sie Ihre Tests erstellen, bevor Sie Code für das Frontend schreiben. Je nachdem, woran Sie arbeiten und was Ihre persönlichen Vorlieben sind, könnten Sie dies als angenehmere Herangehensweise empfinden. Viel Erfolg und gutes Coding :slight_smile:


Dieses Dokument ist versioniert – schlagen Sie Änderungen auf GitHub vor.

15 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

Nur zur Information: Der Pfad /qunit ist veraltet. Es ist jetzt /tests. Ich habe eine Weile gebraucht, um das herauszufinden :slight_smile:

1 „Gefällt mir“