O teste é uma prática essencial na engenharia de software. Ele ajuda a construir um software robusto e de alta qualidade e aumenta a confiança da equipe no código, tornando o aplicativo mais flexível e sujeito a menos erros ao introduzir ou modificar recursos.

Equipes altamente eficientes tornam o teste uma prática central em suas rotinas diárias, e nenhum recurso é lançado antes que os testes automatizados sejam implementados. Alguns desenvolvedores até escrevem os testes antes de escrever os recursos, seguindo um processo chamado TDD (Teste Desenvolvimento Orientado) .

Neste artigo, testaremos React aplicativos com Jest e Biblioteca de teste React , uma combinação popular de uma estrutura de teste JavaScript e um utilitário React para testar componentes. É também a recomendação oficial dada na documentação do React .

O que é teste?

Teste é o processo de automatizar asserções entre os resultados que o código produz e o que esperamos que sejam os resultados.

Ao testar os aplicativos React, nossas afirmações são definidas pela forma como o aplicativo é renderizado e responde às interações do usuário.

Existem muitos tipos diferentes de paradigmas e filosofias de teste. Este artigo se concentrará na criação de testes de unidade e componentes (ou testes de integração).

Introdução à biblioteca de testes Jest and React

O que é Jest?

Jest é uma estrutura de teste de JavaScript que permite aos desenvolvedores executar testes em código JavaScript e TypeScript e integra-se bem com o React.

É uma estrutura projetada com simplicidade em mente e oferece uma API poderosa e elegante para construir testes isolados, comparação de instantâneos, simulação, cobertura de teste e muito mais.

Biblioteca de teste do React

React Testing Library é um JavaScript utilitário de teste criado especificamente para testar componentes do React. Ele simula as interações do usuário em componentes isolados e afirma suas saídas para garantir que a IU esteja se comportando corretamente.

Configurando seu ambiente de teste

Vamos começar instalando as bibliotecas necessárias e configurando o projeto. A maneira mais fácil de colocar um aplicativo React em funcionamento é usando Criar aplicativo React , que vem com o Jest já pré-instalado.

Eu recomendo que você siga as etapas junto com o tutorial executando os comandos e escrevendo o código você mesmo. No entanto, se preferir seguir o código no resultado final do projeto, você pode clonar o projeto de tutorial do GitHub .

Primeiro, crie um aplicativo React:

 npx create-react-app react-jest-tutorial

Agora, instale a Biblioteca de testes do React:

 npm install--save-dev @ testing-library/react

Finalmente, instale bibliotecas adicionais:

 npm install axios

Construindo um aplicativo React para teste

A seguir, construímos um aplicativo mínimo que exibirá os usuários de uma API. Como nosso foco é apenas o front-end, usaremos a API do usuário JSONPlaceHolder . Este aplicativo foi desenvolvido exclusivamente para construir testes.

Substitua o conteúdo do arquivo App.js pelo seguinte:

 import {useEffect, useState} de'react';
importar axios de'axios';
import {formatUserName} de'./utils';
import'./App.css'; function App () { const [usuários, setUsers]=useState ([]); //Carrega os dados do servidor useEffect (()=> { deixe montado=verdadeiro; const getUsers=async ()=> { resposta const=espera axios.get ('https://jsonplaceholder.typicode.com/users'); if (montado) { setUsers (response.data); } }; getUsers (); return ()=> {montado=falso; } }, []); Retorna ( 
Usuários:
{users.length? (
    {users.map (user=> (
  • {user.name} ( {formatUserName (user.username)} )
  • ))}
): (
Carregando usuários...
)}
); } exportar aplicativo padrão;

Em seguida, crie um arquivo chamado utils.js na pasta src e escreva a seguinte função:

 export function formatUserName (username) { return'@'+ nome de usuário;
}

Agora você pode executar o aplicativo com este comando:

 npm start

Depois, você deverá ver esta tela.

Usuários da API
Aplicativo básico que lista os usuários da API com seus nomes de usuário correspondentes.

Construindo um teste de unidade

Os testes de unidade testam unidades ou componentes individuais do software isoladamente. Uma unidade pode ser uma função, rotina, método, módulo ou objeto, e o objetivo do teste é determinar se a unidade produz os resultados esperados para uma determinada entrada.

Um módulo de teste compreende uma série de métodos fornecidos por Jest para descrever a estrutura dos testes. Podemos usar métodos como descrever ou testar da seguinte maneira:

 describe ('minha função ou componente', ()=> { test ('faz o seguinte', ()=> { //Magia acontece aqui });
});

O describe-block é o conjunto de testes, e o test-block (ou simplesmente teste) é o caso de teste. Um conjunto de testes pode ter vários casos de teste, e um caso de teste não precisa estar em um conjunto de testes, embora seja uma prática comum fazer isso.

Dentro de um caso de teste, escrevemos afirmações (por exemplo, esperar em Jest) que validam bem-sucedidas (verde) ou errôneas (vermelho). Cada caso de teste pode ter várias afirmações.

Aqui está um exemplo um tanto trivial de afirmações que resultam com sucesso:

 describe ('verdadeiro é verdadeiro e falso é falso', ()=> { test ('true is truthy', ()=> { esperar (verdadeiro).toBe (verdadeiro); }); test ('falso é falso', ()=> { esperar (falso).toBe (falso); });
});

A seguir, vamos escrever nosso primeiro caso de teste visando a função formatUserName do módulo utils .

Precisamos criar um novo arquivo: utils.test.js . Observe que todos os arquivos de teste usam o padrão {arquivo}.test.js onde {arquivo} é o nome do arquivo de módulo a ser testado.

Nossa função em questão recebe uma string como entrada e produz a mesma string adicionando um @ em seu início. Nossa função de teste pode afirmar que dada uma string, por exemplo, “jc”, a função produzirá “@jc”.

Aqui está o código para o arquivo de teste:

 importar {formatUserName} de"./utils"; descrever ('utils', ()=> { test ('formatUserName adiciona @ no início do nome de usuário', ()=> { expect (formatUserName ('jc')). toBe ('@ jc'); });
});

Descrevemos de forma útil o que é o módulo e para que serve o caso de teste, para que, se eles falharem, tenhamos uma ideia clara do que pode ter dado errado.

Agora que nosso primeiro teste está pronto, podemos executá-lo e ver o que sai. O CRA facilita a execução de todos os testes usando um comando simples npm .

 npm run test

Por enquanto, vamos nos concentrar na execução de um único teste usando:

 npm run test--t'utils'

Fazemos isso porque temos outros testes já criados pelo CRA que precisamos ignorar por enquanto.

Se tudo correr bem, você verá uma saída semelhante a:

Saída bem-sucedida

Observe que um teste foi ignorado (queríamos assim) e que o outro foi aprovado com sucesso.

Mas o que aconteceria se algo desse errado? Vamos adicionar um novo teste ao conjunto de testes utils para descobrir.

 test ('formatUserName não adiciona @ quando já foi fornecido', ()=> { expect (formatUserName ('@ jc')). toBe ('@ jc'); });

Agora a situação é diferente; se o nome de usuário já contém um símbolo @ no início da string, esperamos que a função retorne o nome de usuário conforme fornecido, sem adicionar um segundo símbolo.

Vamos executar:

Resultado do teste com falha

Conforme previsto, o teste falhou e recebemos informações especificamente sobre qual chamada esperada falhou, o valor esperado e o resultado real. Como detectamos um problema com nossa função original, podemos corrigi-lo.

 export function formatUserName (username) { return username.startsWith ('@')? nome de usuário:'@'+ nome de usuário;
}

E execute nossos testes mais uma vez:

Bem-sucedido Teste

Fizemos grandes progressos até agora. Escrevemos dois casos de teste para nosso aplicativo, detectamos um bug graças a esses casos de teste e pudemos corrigi-lo antes de lançá-lo.

Testando componentes com Jest

Testar componentes não é muito diferente de testar funções. A ideia e os conceitos são os mesmos. A diferença está em como escrevemos as afirmações.

Testaremos nosso componente App criando alguns casos de teste e, em cada caso de teste, apresentaremos coisas diferentes que podemos fazer para validar os componentes React.

Nosso primeiro teste será elementar. Isso só validará os renderizadores do componente.

Vá para o arquivo App.test.js (gerado automaticamente pelo CRA) e substitua seu conteúdo por:

 import {render} from'@ testing-library/react';
importar App de'./App'; descrever ('componente do aplicativo', ()=> { test ('renderiza', ()=> { render (); });
})

Semelhante ao anterior, temos um bloco de descrição e um bloco de teste, mas desta vez, usamos a montagem da função render e renderizamos um componente individual isoladamente. Este teste só falhará se houver um erro de compilação ou um erro no componente da função que impeça sua renderização. Embora válido, não é um teste completo porque não executa nenhuma afirmação.

Para consertar, poderíamos fazer a correspondência de conteúdos no componente e ver se eles estão presentes, por exemplo:

 import {render, screen} from'@ testing-library/react';
importar App de'./App'; descrever ('componente do aplicativo', ()=> { test ('renderiza', ()=> { render (); expect (screen.getByText ('Users:')). toBeInTheDocument (); });
})

Nosso novo teste é melhor. Ele valida que o componente pode renderizar, mas também procura um elemento presente no DOM com o texto “Usuários:” , que é, em nosso caso, é, e, portanto, o teste passou com sucesso.

O objeto screen é essencial na Biblioteca de teste do React, como ele fornece métodos auxiliares para interagir com os componentes e seus elementos.

Esperando por operações assíncronas

A seguir, queremos validar se a lista de usuários é renderizada com itens após a conclusão da API. Para isso, podemos escrever um caso de teste da seguinte maneira:

 import {render, screen, waitFor} de'@ testing-library/react';
importar App de'./App'; descrever ('componente do aplicativo', ()=> { test ('exibe uma lista de usuários', async ()=> { render (); expect (screen.getByTestId ('lista de usuários')). toBeInTheDocument (); });
});

No entanto, quando executamos os testes, ele falha com a seguinte mensagem:

Teste falhou no Jest

O motivo da falha é simples: a operação assíncrona (busca) ainda está pendente quando avaliamos a tela, então a mensagem “Carregando usuários…” é exibida em vez da lista de usuários.

A solução é esperar:

 import {render, screen, waitFor} de'@ testing-library/react';
importar App de'./App'; descrever ('componente do aplicativo', ()=> { test ('exibe uma lista de usuários', async ()=> { render (); const userList=await waitFor (()=> screen.getByTestId ('lista de usuários')); expect (userList).toBeInTheDocument (); });
});

E agora os testes estão passando com sucesso.

Zombando com React e Jest

Nossa próxima etapa é validar como o componente reagirá aos dados coletados da API. Mas como podemos testar os dados se não temos certeza de qual seria a resposta da API? A solução para este problema é zombar.

O objetivo da simulação é isolar o código que está sendo testado de dependências externas, como chamadas de API. Isso é conseguido substituindo dependências por objetos controlados que simulam essas dependências.

A simulação é um processo de três etapas:

  1. Importar as dependências
     importar axios de'axios';
    
  2. Zombe da dependência
     jest.mock ('axios');
    
  3. Falsifique as saídas da função
     axios.get.mockResolvedValue ({data: fakeUsers});
    

Vamos vê-los em ação agora:

 importar axios de'axios';
import {render, screen, waitFor} de'@ testing-library/react';
importar aplicativo de'./App'; jest.mock ('axios'); const fakeUsers=[{ "id": 1, "nome":"Usuário de teste 1", "username":"testuser1", }, { "id": 2, "nome":"Usuário de teste 2", "username":"testuser2", }]; descrever ('componente do aplicativo', ()=> { test ('exibe uma linha para cada usuário', async ()=> { axios.get.mockResolvedValue ({dados: fakeUsers}); render (); const userList=await waitFor (()=> screen.findAllByTestId ('item de usuário')); expect (userList).toHaveLength (2); });
});

Uma última observação. Como simulamos axios , cada caso de teste que usa a biblioteca retornará indefinido , a menos que um valor simulado seja passado. Portanto, para recapitular nosso teste de componente completo:

 importar axios de'axios';
import {render, screen, waitFor} de'@ testing-library/react';
importar App de'./App'; jest.mock ('axios'); const fakeUsers=[{ "id": 1, "nome":"Usuário de teste 1", "username":"testuser1", }, { "id": 2, "nome":"Usuário de teste 2", "username":"testuser2", }]; descrever ('componente do aplicativo', ()=> { test ('renderiza', async ()=> { axios.get.mockResolvedValue ({dados: fakeUsers}); render (); expect (screen.getByText ('Users:')). toBeInTheDocument (); }); test ('exibe uma lista de usuários', async ()=> { axios.get.mockResolvedValue ({dados: fakeUsers}); render (); const userList=await waitFor (()=> screen.getByTestId ('lista de usuários')); expect (userList).toBeInTheDocument (); }); test ('exibe uma linha para cada usuário', async ()=> { axios.get.mockResolvedValue ({dados: fakeUsers}); render (); const userList=await waitFor (()=> screen.findAllByTestId ('item de usuário')); expect (userList).toHaveLength (2); });
});

Vamos fazer todos os testes e ver os resultados:

Resultados do teste bem-sucedidos

Conclusão

Testar seu aplicativo React é a chave para produzir aplicativos de alta qualidade e, graças ao React, Jest e à Biblioteca de testes React, é mais fácil do que nunca testar nossos componentes e aplicativos.

Todo o código do aplicativo e testes estão disponíveis em GitHub .

Obrigado por ler!

A postagem Teste de aplicativos com teste Jest and React A biblioteca apareceu primeiro no LogRocket Blog .

Source link