Escreva testes de aceitação e testes de componente para código Ember no Discourse

Automated tests são uma ótima maneira de proteger seu código contra regressões futuras. Muitas pessoas estão familiarizadas com a forma de fazer isso em nossa base de código Rails com rspec, mas o lado Javascript pode ser um enigma para alguns.

Felizmente, hoje em dia é bem fácil adicionar testes básicos ao seu código Ember!

Testes de Componente

No tutorial anterior desta série, adicionamos um componente chamado fancy-snack para exibir nosso lanche com um fundo que desaparece. Vamos escrever um teste para ele. Crie o seguinte arquivo:

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

Para executar o teste, abra seu navegador no seu servidor de desenvolvimento em /qunit?module=component%3Afancy-snack. Seu navegador então executará os testes de componente e exibirá algo como “2 assertions of 2 passed, 0 failed.”

Note que enquanto estiver na página /qunit você pode executar outros testes. Você pode simplesmente selecionar um novo teste na caixa de seleção Module na parte superior da tela.

Vamos analisar o teste para entender como ele funciona.

A linha template diz ao Ember como gostaríamos de inserir nosso componente. É exatamente a mesma marcação que você usaria para colocar o componente em um template handlebars, então deve ser familiar:

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

Note que ele está passando testSnack como o parâmetro snack. Isso é definido no método setup():

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

Eu apenas inseri alguns dados fictícios. Isso é tudo que precisamos fazer para que o Ember renderize o componente. Finalmente, temos algumas asserções no método 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 você usar this.$() você obtém acesso a um seletor jQuery no seu template. As asserções aqui usam esse seletor para obter o valor do título do lanche e da descrição do lanche e compará-los com o que esperamos. Se os valores corresponderem, as asserções passarão e nosso teste estará funcionando.

Vale a pena notar que você não precisa testar cada pequena coisa em um componente como este. Você deve usar algum critério e tentar descobrir quais coisas no seu código provavelmente quebrarão ou causarão confusão a outros desenvolvedores no futuro. Se você testar muitas coisas no seu template, isso significará que será um incômodo para outra pessoa no futuro alterá-lo. Apenas comece pequeno, testando as coisas mais óbvias, e com o tempo você pegará o jeito.

Testes de Aceitação

Testes de aceitação são frequentemente mais fáceis de escrever e podem ser mais poderosos do que testes de componente, pois testam sua aplicação da mesma forma que um usuário faria em seu navegador. Eu costumo começar com testes de aceitação e, se estiver criando um componente complicado, adiciono testes para ele também.

Veja como podemos escrever um teste de aceitação que visitará nossa rota /admin/snack e confirmará que o lanche foi renderizado:

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

O test() neste caso quase parece inglês! O primeiro comando diz para visitar o URL /admin/snack. Depois disso, há um método andThen(). Este método é necessário para garantir que todo o trabalho em segundo plano seja concluído antes que os testes continuem. Como o Javascript e o código Ember são assíncronos, precisamos garantir que o Ember tenha terminado tudo o que precisa fazer antes que nossas asserções sejam executadas. Finalmente, ele testa para ver se o elemento .fancy-snack-title está presente.

No entanto, se você executar este teste visitando /qunit?module=Acceptance%3A%20Snack, você descobrirá que o teste falhará, devido a um erro AJAX.

Se você se lembra, nosso código inclui um lado Rails e um lado Javascript que realizou uma solicitação AJAX para obter seus dados. O teste de aceitação executou o lado Javascript, mas não sabia o que fazer para obter seus dados do Rails.

Para corrigir isso, precisamos adicionar uma resposta falsa, usando a excelente biblioteca pretender. Abra o arquivo test/javascripts/helpers/create-pretender.js e procure a linha que diz:

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

Logo abaixo dela, adicione uma linha para retornar um objeto de lanche falso para nosso teste de aceitação funcionar:

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

Você pode ler o código acima como “para qualquer solicitação para /admin/snack.json, responda com a seguinte response.”

Se você atualizar o URL /qunit?module=Acceptance%3A%20Snack, seu teste de aceitação deve recuperar seus dados via pretender e os testes devem passar.

Para onde ir a partir daqui

Você pode tentar construir um pequeno recurso e adicionar testes para garantir que ele funcione. Você pode até tentar usar TDD criando seus testes antes de escrever qualquer código no front-end. Dependendo do que você está trabalhando e de suas preferências pessoais, você pode achar que esta é uma maneira mais agradável de fazer isso. Boa sorte e boas codificações :slight_smile:


Este documento é controlado por versão - sugira alterações no github.

15 curtidas

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 curtidas

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 curtidas

Apenas uma observação de que o caminho /qunit está obsoleto. Agora é /tests. Levei um tempo para descobrir isso :slight_smile:

1 curtida