Teste angular: teste de componentes

Dec 06 2022
Visão geral No artigo anterior, defini “Teste de unidade” e como podemos aplicar esses testes ao nosso aplicativo Angular. Concordamos que, por definição, nossa lógica de negócios deve residir fora de nossos componentes, e a maior parte de nossa funcionalidade residirá em pipes, diretivas e serviços, o que significa que a maioria de nossos testes de unidade testará esses tipos de classes.

Visão geral

No artigo anterior , defini “Teste de Unidade” e como podemos aplicar esses testes em nosso aplicativo Angular. Concordamos que, por definição, nossa lógica de negócios deve residir fora de nossos componentes, e a maior parte de nossa funcionalidade residirá em pipes, diretivas e serviços, o que significa que a maioria de nossos testes de unidade testará esses tipos de classes. Nesse artigo, também postei uma essência de um componente Angular com sua lógica de modelo movida do componente para um canal, deixando apenas um Input()na definição de classe e alguns modelos. Todos nós concordamos que, a qualquer momento, alguém pode entrar e adicionar ou remover elementos no elemento, e não há quantidade de testes de unidade que possam capturar essas mudanças.

Portanto, se você não pode usar testes de unidade para testar um componente adequadamente, resta apenas o componente, a integração ou o teste de ponta a ponta.

O teste de integração pode funcionar, mas, por definição, o teste de integração ocorre quando você testa unidades individuais e as combina para testar como um grupo. Então, por exemplo, você pode testar ComponentAcom ComponentB, e isso provavelmente é bom em alguns casos. Mas o que acontece quando você se integra ComponentAcom ComponentC? Você se sente confortável em dizer que o primeiro teste que criou é bom o suficiente para enviar seu produto para produção?

De acordo com os documentos Angular :

Os blocos de construção básicos da estrutura Angular são componentes Angular…

Os componentes são projetados para serem combinados e consumidos por diferentes componentes para construir seu aplicativo. Portanto, você precisa ser capaz de garantir que tenha alguma fonte de verdade para o DOM, especificamente seus recursos Inpute Outputpropriedades de acessibilidade e qualquer estilo que considere pertinente para garantir que seja sempre válido e que você não precise testar manualmente.

Vamos voltar ao componente Header:

À primeira vista, não há muito o que testar . Em um mundo ideal, saberíamos que o NameDisplayPipepossui testes que validam os valores fornecidos pelo componente e retornam o que esperamos. Mas o que acontece se alguém ajustar acidentalmente o h1para um h2? E se alguém remover acidentalmente a inicialização do título?

Teste de componentes para o resgate

O teste de componentes é incrível, pois elimina a necessidade de testar manualmente muitas coisas que nos acostumamos a testar manualmente. Por exemplo, conheço poucos desenvolvedores que pensam em definir a estrutura do template do componente (a parte mais crucial) através de testes; no entanto, conheço muitos QAs e designers que verificam manualmente essas coisas. No entanto, é algo que geralmente não discutimos. Estamos convencidos de que testamos nossa funcionalidade e comportamentos, mas só estamos interessados ​​em testar modelos quando o código estiver em produção. É simplesmente uma reflexão tardia.

Suponha que eu receba uma simulação de uma página com um cabeçalho, um corpo e um rodapé. Por causa deste artigo, o conteúdo do corpo não importa, mas como um item de trabalho, devo fazer todas as três coisas em um sprint. Então haveria pelo menos quatro componentes : a HeaderComponent, BodyComponent, FooterComponent, e a PageComponentque integra os outros três…

Já criamos o componente de cabeçalho, mas vamos fingir que não. Se tivermos maquetes do cabeçalho, poderíamos definir o que precisaria ser sempre verdadeiro neste componente:

  1. O componente deve envolver seu conteúdo em um elemento de cabeçalho.
  2. Por padrão, se um usuário não estiver conectado, o cabeçalho deve dizer: “Olá, usuário” em um arquivo h1.
  3. Se um usuário estiver logado, o cabeçalho deve dizer: “Hello, {{ User Name }}” em um arquivo h1.

Para testes de componentes, você pode usar Jasmine, Jest ou Cypress. Com Jasmine e Jest, você depende do TestBed e usa um acessório para pegar elementos e afirmá-los. Com o Jest, você não vê o modelo em um DOM real, portanto, quase não oferece nenhum benefício real. Jasmine funciona muito bem aqui; fora da caixa, ele faz quase tudo o que você deseja. Ou seja, poder percorrer os testes no tempo e ver instantâneos de seus testes. Como embaixador do Cypress, você provavelmente adivinhou que prefiro usar o Cypress para isso e, a partir do Cypress 10.5 , podemos fazer isso acontecer!

TDD com teste de componentes do Cypress

O teste de componentes do Cypress tem uma sintaxe muito semelhante ao teste de ponta a ponta do Cypress. Se você sabe como escrever um “Teste Cypress”, você sabe como escrever um teste de componente. Usando os 3 casos de teste que criei acima, posso estruturar rapidamente um arquivo de especificações de testes relacionados a cada um deles:

Se você já viu um teste Cypress no passado, isso deve parecer bastante familiar. Se ainda não, vamos dar uma olhada em cada peça:

Deve estar dentro de um elemento de cabeçalho:

it('should contain a header', () => {    
  cy.mount(HeaderComponent);     
  cy.get('header')      
    .should('exist')      
    .should('be.visible');  
});

O cy.get('header')é o único comando a seguir. Usaremos javascript para obter o elemento de cabeçalho e, em seguida, afirmar que ele não apenas existe, mas também é visível. Este teste falhará ao fazer TDD até adicionarmos um <header></header>elemento ao modelo.

Por padrão, se um usuário não estiver logado, o cabeçalho deve dizer: “Olá, usuário” em h1.

it('should have an h1 that has a greeting', () => {  
  cy.mount(HeaderComponent);     
  cy.get('h1')      
    .should('have.text', 'Hello, User');  
});

Se um usuário estiver logado, o cabeçalho deve dizer: “Hello, {{ User Name }}” em um h1.

it('should display a user name if name is provided', () => {    
  cy.mount(HeaderComponent, {      
    componentProperties: {        
      title: {          
        firstName: 'John',
        lastName: 'Doe'
      }      
    }    
  });       cy.get('h1')      
    .should('have.text', 'Hello, John Doe');
});

Fácil, certo?

Resumo

O teste de componentes é interessante! Não é um conceito novo, mas é mais rápido do que tínhamos acesso até a implementação do Cypress. Como você pode ver no canto superior direito do painel esquerdo, são necessários 147 ms para executar esses três testes, e cada teste leva menos de alguns minutos para ser gravado se o modelo do seu componente já estiver definido. Com esses testes como ponto de partida para esse componente de cabeçalho, se alguém alterar algo que não esteja de acordo com as três especificações já existentes, sabemos que o componente está “quebrado” e precisamos resolvê-lo. Como isso está apenas testando a instância do HeaderComponent, não podemos chamá-lo de teste de integração. Não podemos chamar isso de teste de unidade, pois nenhuma funcionalidade está sendo testada. Isso, meus amigos, é um teste de componente!

Esse já era o seu entendimento sobre Teste de componentes em Angular? Seus testes Jasmine ou Jest são tão limpos e rápidos? Deixe-me saber como o seu contrasta com este!

Vejo você no próximo capítulo, onde revisarei o teste de integração.