Testes automatizados em React

Em Como mantemos a qualidade de software nos projetos do Luizalabs, temos uma visão geral de qualidade no processo de desenvolvimento de software, incluindo testes automatizados, code review, integração contínua, monitoramento, entre outros tópicos.

É compreensível que testes em frontend costumam ser um assunto obscuro para os desenvolvedores, pois antes de trabalharmos nessa nova geração do javascript, haviam poucas maneiras de testar a parte visual e interativa da aplicação. Hoje, com a evolução da comunidade javascript, frameworks e bibliotecas, temos diversos recursos para efetuar os devidos testes e manter a qualidade nos projetos.

Tendo em mente a seguinte pirâmide de testes, iremos focar nesse artigo nos testes unitários, sendo que eles são mais baratos e rápidos de serem feitos, e garantem uma base sólida para o software.

Vale lembrar que não existe maneira única e universal de escrever testes, seja em react ou qualquer outra tecnologia. Devemos analisar o contexto e utilizar padrões que se encaixam em nossa realidade.

Para exemplificar, utilizaremos React, criado com create-react-app.

Bibliotecas Utilizadas

JEST

Biblioteca padrão de testes do create-react-app. Ele nos permite testar snapshots, que de acordo com a documentação oficial:

Snapshot tests are a very useful tool whenever you want to make sure your UI does not change unexpectedly.
A typical snapshot test case for a mobile app renders a UI component, takes a screenshot, then compares it to a reference image stored alongside the test. The test will fail if the two images do not match: either the change is unexpected, or the screenshot needs to be updated to the new version of the UI component.

Ou seja, os snapshots são como fotografias da interface, e garantem que a visualização da sua aplicação não mudará de forma inesperada.

Enzyme

Biblioteca criada pelo Airbnb, permite ao desenvolvedor simplificar a renderização de componentes nos testes.

Enzyme is a JavaScript Testing utility for React that makes it easier to assert, manipulate, and traverse your React Components’ output.

Criando o projeto exemplo

Vamos criar um projeto utilizando create-react-app. O projeto também pode ser visualizado no github (https://github.com/thiagoferreiraw/react-testnig):

$ npm install -g create-react-app
$ create-react-app react-testing
$ cd react-testing
$ npm install -S prop-types

Para verificar se o projeto foi criado com sucesso, executamos o comando de testes:

$ npm test

O output deverá ser conforme abaixo, indicando que o teste padrão passou com sucesso.

Instalando as dependências e configurando o ambiente

Com o comando abaixo, vamos instalar apenas o enzyme (o jest já vem configurado por padrão)

$ npm i --save-dev enzyme enzyme-adapter-react-16 enzyme-to-json

Para configurar o ambiente de testes do enzyme, crie um arquivo chamado react-testing/src/setupTest.js com o seguinte conteúdo:

// react-testing/src/setupTests.js
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

Criando um componente exemplo

A proposta é bem simples, um componente que recebe a propriedade isLoggedIn e username. A partir daí, o componente deve renderizar as tarefas para o usuário logado, ou uma página de login para o usuário não autenticado.

Escrevendo os testes

Antes de escrever os testes, precisamos ter em mente o que vale a pena ser testado no componente. No nosso caso, verificaremos as saídas conforme os parâmetros passados via props:

  • Renderização da tela de login
  • Renderização do usuário logado, com tarefas.
  • Renderização do usuário logado, sem tarefas.

Opção 1: Verificações manuais com Enzyme

Nessa abordagem, nós montamos o componente utilizando Enzyme e fazemos as verificações (asserts) manualmente:

Se os testes falharem, essa será a nossa visualização:

Opção 2: Utilizando snapshots

Fazer as validações manuais com Enzyme é bem útil, porém temos uma forma mais simples de fazer verificações na interface sem precisar escrever todas as condições esperadas. Sendo o código:

Nós substituímos as verificações manuais e adicionamos apenas expect(toJson(app)).toMatchSnapshot(). Sendo assim, será gerado um arquivo na pasta __snapshots__ automaticamente, e esse arquivo contém toda a estrutura de renderização do componente. Se por acaso alterarmos algo e não atualizarmos o snapshot, o teste quebrará dessa forma:

Bem prático, não? Pra atualizar o snapshot, basta pressionar “u”, e o jest irá considerar a nova visualização como correta.

Relatório de cobertura

Para verificar a cobertura de testes dos componentes criados, basta rodar o comando:

$ npm test -- --coverage

Temos a opção de visualizar o relatório no navegador, para uma visualização mais clara, além de poder clicar nos componentes e abrir cada um com mais detalhes. O arquivo é gerado em:

/projeto/coverage/lcov-report/index.html
# Basta abrir com qualquer navegador.

Conclusão

Em desenvolvimento guiado por testes no frontend, temos ótimas bibliotecas para testar nossos componentes. Cada projeto pode ter diferentes estratégias de teste, dependendo de vários fatores, mas é uma prática indispensável hoje em dia.

Testes garantem que podemos evoluir nosso software tranquilamente e com qualidade, garantindo mais confiabilidade aos usuários ;)

Alguma dúvida? Estamos sempre abertos à discussão! Basta comentar nesse artigo ❤

Referências:

Cover Photo by Max Nelson on Unsplash