Scrivere test di accettazione e di componente per il codice Ember in Discourse

I test automatizzati sono un ottimo modo per proteggere il proprio codice da future regressioni. Molte persone sono familiari con il modo di farlo nel nostro codicebase Rails con rspec, ma la parte Javascript può risultare un po’ enigmatica per alcuni.

Fortunatamente, al giorno d’oggi è piuttosto facile aggiungere test di base al proprio codice Ember!

Test dei Componenti

Nel tutorial precedente di questa serie abbiamo aggiunto un componente chiamato fancy-snack per visualizzare il nostro snack con uno sfondo sfumato. Scriviamo un test per esso. Crea il seguente file:

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

Per eseguire il test, apri il browser sul server di sviluppo alla pagina /qunit?module=component%3Afancy-snack. Il browser eseguirà quindi i test dei componenti e produrrà un output simile a «2 assertions of 2 passed, 0 failed.»

Nota che mentre sei sulla pagina /qunit puoi eseguire altri test. Puoi semplicemente selezionare un nuovo test dal menu a tendina Module in alto sullo schermo.

Analizziamo il test per capire come funziona.

La riga template dice a Ember come desideriamo inserire il nostro componente. È esattamente lo stesso markup che si userebbe per posizionare il componente in un template handlebars, quindi dovrebbe essere familiare:

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

Nota che viene passato testSnack come parametro snack. Questo è definito nel metodo setup():

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

Ho inserito solo alcuni dati fittizi. È tutto ciò che dobbiamo fare per far rendere il componente a Ember. Infine, abbiamo alcune asserzioni nel metodo 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!');
}

Se si usa this.$() si ottiene accesso a un selettore jQuery nel template. Le asserzioni qui usano quel selettore per recuperare il valore del titolo dello snack e della descrizione dello snack e confrontarli con ciò che ci aspettiamo. Se i valori corrispondono, le asserzioni superano e il nostro test funziona correttamente.

È utile notare che non è necessario testare ogni minimo dettaglio in un componente come questo. Dovresti usare buon senso e cercare di capire quali parti del tuo codice sono più soggette a rompersi o a causare confusione ad altri sviluppatori in futuro. Se si testano troppe cose nel template, sarà un fastidio per qualcun altro in futuro modificarlo. Inizia in piccolo, testando le cose più ovvie, e col tempo prenderai la mano.

Test di Accettazione

I test di accettazione sono spesso più facili da scrivere e possono essere più potenti dei test dei componenti, poiché testano la tua applicazione allo stesso modo in cui un utente lo farebbe nel proprio browser. Spesso inizio con i test di accettazione e, se sto creando un componente complesso, aggiungo anche dei test per esso.

Ecco come possiamo scrivere un test di accettazione che visiterà la nostra rotta /admin/snack e confermerà che lo snack è stato reso:

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

In questo caso, il test() è quasi leggibile come inglese! Il primo comando dice di visitare l’URL /admin/snack. Dopo di che, c’è un metodo andThen(). Questo metodo è necessario per assicurarsi che tutto il lavoro in background sia terminato prima che i test continuino. Poiché il codice Javascript ed Ember è asincrono, dobbiamo assicurarci che Ember abbia finito tutto ciò che deve fare prima che le nostre asserzioni vengano eseguite. Infine, il test verifica se l’elemento .fancy-snack-title è presente.

Tuttavia, se esegui questo test visitando /qunit?module=Acceptance%3A%20Snack, scoprirai che il test fallirà a causa di un errore AJAX.

Se ti ricordi, il nostro codice include sia una parte Rails che una parte Javascript che ha eseguito una richiesta AJAX per ottenere i propri dati. Il test di accettazione ha eseguito la parte Javascript, ma non sapeva cosa fare per ottenere i dati da Rails.

Per correggere questo, dobbiamo aggiungere una risposta fittizia, usando l’eccellente libreria pretender. Apri il file test/javascripts/helpers/create-pretender.js e cerca la riga che dice:

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

Subito sotto, aggiungi una riga per restituire un oggetto snack fittizio affinché il nostro test di accettazione possa funzionare:

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

Puoi leggere il codice sopra come «per qualsiasi richiesta a /admin/snack.json, rispondi con la seguente response.»

Se aggiorni l’URL /qunit?module=Acceptance%3A%20Snack, il tuo test di accettazione dovrebbe recuperare i dati tramite pretender e i test dovrebbero superare.

Dove andare da qui

Potresti provare a costruire una piccola funzionalità e ad aggiungere test per assicurarti che funzioni. Potresti persino provare a usare il TDD creando i tuoi test prima di scrivere qualsiasi codice sul front end. A seconda di su cosa stai lavorando e delle tue preferenze personali, potresti trovare questo un modo più piacevole di procedere. In bocca al lupo e buon coding :slight_smile:


Questo documento è sottoposto a controllo di versione - suggerisci modifiche su github.

15 Mi Piace

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 Mi Piace

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 Mi Piace

Solo una nota: il percorso /qunit è obsoleto. Ora è /tests. Mi ci è voluto un po’ per capirlo :slight_smile:

1 Mi Piace