No último artigo eu falei um pouco sobre testes no front-end, os motivos de testar suas aplicações, tipos de testes e principais ferramentas para isso.
Neste artigo iremos escrever nosso primeiro teste para um componente de uma aplicação React. Vamos lá!
Criando o componente
Suponha que precisamos testar o seguinte componente React chamado "Counter", que exibe um contador que é incrementado sempre que um botão é clicado:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function incrementCount() {
setCount(count + 1);
}
return (
<div>
<h1>Contador: {count}</h1>
<button onClick={incrementCount}>Incrementar</button>
</div>
);
}
export default Counter;
Esse componente não recebe nenhuma prop, ele tem apenas um estado, o contador (count) que é incrementado sempre que o botão "Incrementar" é clicado.
Perfeito! Então vamos criar um teste para este componente.
Testando o componente <Counter />
Para testar componentes React eu vou usar o Jest e o Testing Library. O Jest é bem fácil de usar e servirá para fazermos asserções sobre nosso código, enquanto que o Testing Library serve para para facilitar a renderização dos componentes e a interação com eles.
Se você criou sua aplicação React com o Create React App (CRA) é provável quee já tenha tanto o jest como os recursos do React Testing Library no seu projeto. Se não, se você usou o Vite por exemplo, pode ser que precise instalar essas dependências. Para instalar é bem simples, é só digitar no seu terminal
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
Ambiente preparado, então vamos ao teste.
Vamos criar um arquivo de teste para o componente Counter, com o nome Counter.test.js
:
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/extend-expect';
import Counter from './Counter';
describe('Counter', () => {
it('Deve renderizar o contador sem erros', () => {
render(<Counter />);
const textoContador = screen.getByText('Contador: 0');
expect(textoContador).toBeInTheDocument();
});
it('Deve incrementar o contador quando o botão é clicado', () => {
render(<Counter />);
const botaoIncrementar = screen.getByText('Incrementar');
const novoTextoContador = screen.getByText('Contador: 1');
userEvent.click(botaoIncrementar);
expect(novoTextoContador).toBeInTheDocument();
});
});
Tá, mas o que significa cada linha deste teste? Vou explicar.
Primeiro precisamos fazer as importações dos utilitários que iremos precisar. Para renderizar nosso componente importamos o render
, para observar o que foi renderizado utilizamos screen
e para fazer consultas aos elementos desse componente utilizamos o getByText()
. Não se preocupe com essas funções e utilitários agora, irei trazer explicações mais detalhadas sobre cada um em outros artigos.
Para agrupar e organizar melhor os testes deste componente, eu utilizo o describe
e dou uma descrição que nada mais é que o nome do componente, mas você pode fazer descrições mais detalhadas.
O teste em si mesmo, só começa quando declaramos ele, com o it()
. O it
recebe dois parâmetros, que é a descrição do cenário de teste e uma função que executará o teste.
Como boa prática, eu gosto de seguir uma ordem ao escrever um cenário de teste.
- Renderizo o componente que estou testando com o render;
- Faço uma consulta a um elemento usando o
screen
e uma query de consulta, neste caso ogetByText()
; - Faço uma asserção, que é a comparação entre o que eu espero e o que eu recebo no meu teste;
Neste primeiro teste eu tenho dois cenários:
- O primeiro verifica se o componente
<Counter />
é renderizado sem erros e se o contador é iniciado com o valor 0. - O segundo simula um clique no botão "Incrementar" e verifica se o contador é incrementado corretamente.
O clique no botão é realizado utilzando o utilitário userEvent
, que possui uma grande quantidade de eventos que simulam interações com a página, como digitar em campos de texto, selecionar opções em um select, etc.
Como outra boa prática eu gosto de salvar o que é retornado das consultas em variáveis e dar nome à elas que sejam significativos. Por exemplo, eu usei o textoContador para receber o que foi retornado de resultado da minha consulta a este elemento. E chamei de botaoIncrementar o botão que obtemos ao fazer a consulta pelo seu texto também.
Você pode perceber que ao fazer isso, fica bem mais simples de ler o teste, por exemplo, nesta asserção:
expect(textoContador).toBeInTheDocument();
Ao ler eu claramente sei o que esse teste faz, que é: "Espero que o texto do contador esteja no documento".
Executando os testes
Para executar os testes de sua aplicação é bem simples, é só digitar em um terminal
npm test
Este script vem como padrão ao iniciar a aplicação com o CRA.
E prontinho! Em menos de cinco minutos você escreveu o que chamamos de testes de unidade para um componente React. Este tipo de teste é simples, onde estamos testando uma unidade, no caso um componente, que é uma função, e como esse componente tem sua própria responsabilidade, que é renderizar o contador e incrementá-lo ao clicar em um botão, ele pode ser facilmente testado com testes esse.
Dependendo do projeto, pode ser necessário escrever testes mais complexos e abrangentes para garantir a qualidade do código.
Maneiro né? Se está gostando dessa série de artigos sobre testes no Front-end comenta aí o que tem achado e se esse conteúdo tem te ajudade de alguma forma!
Até a próxima!