E aí, você testa seus códigos? Hoje o dataholic Dakson Chaves vai te explicar a relevância e importância que os testes têm para um dev. Bora conferir!
Então, o que são testes unitários?
A palavra teste é um substantivo que tem sua origem no latim - testis – no dicionário “Todo mecanismo que busca verificar ou provar a verdade de”.
O nome é autoexplicativo, é um algoritmo construído para colocar a prova, as menores unidades de código do seu projeto. Outra definição é do Roy Osherove:
"Um teste unitário é um pedaço de código automatizado que executa uma funcionalidade unitária no sistema e depois faz uma conferência singular sobre uma hipótese no comportamento daquela determinada funcionalidade unitária".
Exemplo de unidade código:
Figura 1 //Código JavaScript que soma duas variáveis "a" e "b".
Por que testar?
Fazer os testes unitários pode evitar erros e eventos de Regressão, que são bgus dados como resolvidos anteriormente no projeto, isso possibilita uma entrega com mais qualidade. Além disso, é gerada automaticamente uma documentação que pode ser usada no projeto.
Por último, mas não menos importante, a redução de custos no processo de desenvolvimento, evitando retrabalho e facilitando a manutenção do código.
Na Documentação do React
Você pode testar componentes React de forma similar como se testa outros códigos JavaScript.
Há algumas maneiras de testar componentes React. Em geral, os testes podem ser feitos de duas formas:
Renderizando árvores de componentes em um ambiente de testes simplificado e confirmando o seu output.
Executando uma aplicação completa em um ambiente de navegador real (também conhecido como testes “end-to-end”).
Esta seção da documentação se concentra nas estratégias de teste para o primeiro caso. Embora os testes end-to-end completos possam ser muito úteis para impedir regressões em casos importantes, esses testes não estão relacionados a componentes React em particular e estão fora do escopo desta seção.
Tradeoffs
Ao escolher uma ferramenta de teste, vale a pena considerar alguns tradeoffs:
Velocidade de iteração vs ambiente real: Algumas ferramentas oferecem um ciclo de feedback muito rápido entre fazer uma alteração e ver o resultado, mas não reflete o comportamento do navegador com precisão. Outras ferramentas podem usar um ambiente de navegador real, mas reduzem a velocidade da iteração e são mais precárias em um servidor de integração contínua.
Quanto mock eu devo usar: Nos componentes, a diferença entre um teste de “unidade” e um de “integração” pode ser confusa. Se você estiver testando um formulário, o teste também deve testar os botões dentro dele? Ou um componente de botão deve ter seu próprio conjunto de testes? A refatoração de um botão deve falhar o teste do formulário?
Diferentes respostas podem funcionar para diferentes times e produtos.
Ferramentas recomendadas
Jest é um test runner JavaScript, que te permite acessar o DOM através do jsdom. Mesmo o jsdom sendo apenas uma aproximação de como um navegador funciona, é bom o suficiente para testar componentes React. Jest oferece uma excelente velocidade de iteração combinada com recursos poderosos como mock de módulos e temporizadores para que você tenha mais controle sobre como o código é executado.
React Testing Library é um conjunto de utilitários que permitem testar componentes React sem depender dos detalhes de implementação. Essa abordagem facilita a refatoração e também te orienta para as melhores práticas de acessibilidade. Embora não forneça uma maneira de renderizar “superficialmente” um componente sem seus filhos, um test runner como o Jest permite fazer isso através de mock.
Exemplos práticos de utilização
Para continuar vou criar um exemplo simples de teste no React com o nome “teste-unitario”. Dentro do terminal digite o npx create-react-app <meu-app>, para criar um projeto.
Figura 2 //Abrindo a pasta “teste-unitario” do projeto criado pelo React no VSCode.
Ao criar o projeto há uma organização de estruturas de pastas, mas nesse caso vamos nos ater apenas ao arquivo de teste que está dentro da pasta src, App.test.js.
Figura 3 // Pasta src e arquivo App.test.js na organização do React.
Precisamos entender o que rola dentro desse arquivo, a princípio
Figura 4 // Código do arquivo App.test.js
De cara percebemos a importação da biblioteca @testing-library que vai interagir com DOM (Document Object Model). Em relação ao render e screen que são usados para capturar os elementos e não necessariamente renderizar a tela. Na sequência a importação do App que é o componente que vai ser testado.
O método test() – tem a missão de chamar os testes que serão executados dentro do método. Dentro contém o que é esperado e o que não é.
Então ocorre que:
É renderizado o componente
Criada uma variável (linkElement)
A variável recebe do método screen o elemento que possuir o texto learn react
O esperado é que a variável esteja no documento
O comando Yarn test ou npm test, que já vem por padrão configurado no arquivo package.json, chama o executor de testes criado pelo Facebook – o Jest , sem nenhuma alteração, ao rodá-lo no terminal o Jest que examinará seu código e vai apresentar uma tela de PASS, com informações dos testes quais deles passaram e quais falharam, conforme Figura 5.
Figura 5 // Trecho do arquivo packge.json que vem por padrão no scripts.
Figura 6 // Execução do teste sem alteração (yarn test).
Vamos fazer uma alteração no App.js e verificar como roda o teste. Um elemento simples de iteração interessante para exemplificar é checkbox.
Figura 7 // App.js com o nosso novo bloco de código, o checkbox, para testar.
Figura 8 // Tela inicial padrão do create-react-app com nosso checkbox para testar.
Agora vamos alterar o App.test.js e colocar a prova nosso código simulando uma ação de click do usuário. Começaremos com import userEvent from '@testing-library/user-event', sem o qual não teremos sucesso no teste.
Figura 9 //App.test.js alterado para testar nosso checkbox.
O userEvent é uma biblioteca que nos permite executar outras ações. A testing library fornece o método fireEvent integrado, mas é mais recomendável que se use o userEvent.
Figura 10 // Resultado do teste.
Nesse ponto é legal mencionar outras funcionalidades bastante utilizadas – Mocks e Snapshot.
Mocks ou Mock Objects são utilizados quando precisamos simular chamados reais de dados, permitindo a criação de módulos, funções com retorno controláveis. Por exemplo, uma página de autenticação de usuário, onde são solicitados e-mail e senha. Nesse caso no código de teste se utiliza informações falsas para agilizar o processo.
Exemplo da própria Documentação React:
Figura 11 // Exemplo de Mock da documentação React.
Snapshots são testes para prevenir quebra de layout e eventuais bugs na UI (User Interface) do projeto. Primeiramente, não esquecer de importar o react-test-renderer – que é um pacote que oferece um renderizador de componentes sem precisar de um código complexo para manipular o DOM.
Figura 12 //Exemplo de código de teste UI.
Verifica-se que nosso componente é passado como argumento para o renderer e depois transformado em JSON.
Normalmente o Snapshot é salvo em um arquivo como esse:
Figura 13 // Exemplo de arquivo snashot JSON.
Conclusão
Independente do projeto que estivermos trabalhando é uma boa prática testar nossos códigos, é o mínimo que podemos fazer para garantir a qualidade do produto sem perder agilidade. E assim garantir que o software não esteja sujeito a erros e evitar eventos de regressão. Além disso, os testes podem ser usados como documentação para o projeto.
Portanto, são muitas as vantagens dos testes unitários e hoje não dá mais para pensar em desenvolvimento de software sem pensar em testes unitários.
Referências: