Ir para o conteúdo principal

Migrar do Enzyme

[Tradução Beta Não Oficial]

Esta página foi traduzida por PageTurner AI (beta). Não é oficialmente endossada pelo projeto. Encontrou um erro? Reportar problema →

Esta página é destinada a desenvolvedores com experiência em Enzyme que buscam entender como migrar para o React Testing Library. Não abordamos detalhadamente como migrar todos os tipos de testes, mas trazemos informações úteis para quem está comparando Enzyme com React Testing Library.

O que é React Testing Library?

React Testing Library faz parte do projeto open-source Testing Library. O projeto inclui diversas outras ferramentas e bibliotecas úteis para escrever testes mais concisos e eficientes. Além do React Testing Library, veja algumas bibliotecas do projeto que podem ajudar você:

  • @testing-library/jest-dom: jest-dom fornece um conjunto de matchers personalizados para Jest. Eles tornam seus testes mais declarativos, fáceis de ler e manter.

  • @testing-library/user-event: user-event simula eventos reais do navegador durante a interação do usuário com elementos da página. Por exemplo, userEvent.click(checkbox) alteraria o estado do checkbox.

Por que usar o React Testing Library?

Enzyme é uma biblioteca poderosa e seus contribuidores fizeram muito pela comunidade JavaScript. Muitos dos mantenedores do React Testing Library inclusive usaram e contribuíram com o Enzyme antes de desenvolver nossa biblioteca. Então nosso agradecimento aos contribuidores do Enzyme!

O principal objetivo do React Testing Library é aumentar a confiabilidade dos testes avaliando componentes da forma como usuários os utilizam. Usuários não se importam com processos internos - eles interagem apenas com a saída visível. Em vez de acessar APIs internas ou avaliar o state, você ganha mais confiança testando com base no resultado renderizado.

O React Testing Library resolve um problema comum em testes com Enzyme: o incentivo a testar detalhes de implementação. Testes assim impedem refatorar componentes sem alterar testes correlatos. Como resultado, os testes reduzem velocidade de desenvolvimento e produtividade. Até pequenas mudanças podem exigir reescrever testes, mesmo sem alterar a saída do componente.

Reescrever testes com React Testing Library vale a pena: você troca testes que atrapalham por testes que dão mais confiança e aumentam sua produtividade a longo prazo.

Como migrar do Enzyme para React Testing Library?

Para migração bem-sucedida, recomendamos abordagem incremental: execute ambas bibliotecas lado a lado no mesmo projeto, convertendo testes do Enzyme para React Testing Library um por um. Isso permite migrar até aplicações grandes e complexas sem impactar negócios, com trabalho colaborativo distribuído ao longo do tempo.

Instalando React Testing Library

Primeiro, instale o React Testing Library e a biblioteca auxiliar jest-dom (veja este guia para instruções completas de instalação).

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

Importando React Testing Library nos testes

Se estiver usando Jest (outros frameworks são suportados), importe estes módulos no arquivo de teste:

// import React so you can use JSX (React.createElement) in your test
import React from 'react'

/**
* render: lets us render the component as React would
* screen: a utility for finding elements the same way the user does
*/
import {render, screen} from '@testing-library/react'

A estrutura do teste pode ser a mesma que você usaria com Enzyme:

test('test title', () => {
// Your tests come here...
})

Nota: você também pode usar blocos describe e it com o React Testing Library. O React Testing Library não substitui o Jest, apenas o Enzyme. Recomendamos test porque ajuda com isto: Evite Aninhamento ao Testar.

Exemplos básicos de migração do Enzyme para o React Testing Library

É importante lembrar que não há uma correspondência direta entre os recursos do Enzyme e os do React Testing Library. Muitos recursos do Enzyme resultam em testes ineficientes de qualquer forma, então alguns recursos que você está acostumado com o Enzyme precisam ser abandonados (sem necessidade de variável wrapper ou chamadas wrapper.update(), etc.).

O React Testing Library possui consultas úteis que permitem acessar os elementos do seu componente e suas propriedades. Mostraremos alguns testes típicos com Enzyme junto com alternativas usando o React Testing Library.

Vamos supor que temos um componente Welcome que exibe uma mensagem de boas-vindas. Vamos analisar testes com Enzyme e React Testing Library para aprender como podemos testar este componente:

Componente React

O seguinte componente obtém um name via props e exibe uma mensagem de boas-vindas em um elemento h1. Ele também possui um campo de texto que os usuários podem alterar para um nome diferente, e o modelo é atualizado de acordo. Veja a versão ao vivo no CodeSandbox.

const Welcome = props => {
const [values, setValues] = useState({
firstName: props.firstName,
lastName: props.lastName,
})

const handleChange = event => {
setValues({...values, [event.target.name]: event.target.value})
}

return (
<div>
<h1>
Welcome, {values.firstName} {values.lastName}
</h1>

<form name="userName">
<label>
First Name
<input
value={values.firstName}
name="firstName"
onChange={handleChange}
/>
</label>

<label>
Last Name
<input
value={values.lastName}
name="lastName"
onChange={handleChange}
/>
</label>
</form>
</div>
)
}

export default Welcome

Teste 1: Renderizar o componente e verificar se o valor do h1 está correto

Teste com Enzyme

test('has correct welcome text', () => {
const wrapper = shallow(<Welcome firstName="John" lastName="Doe" />)
expect(wrapper.find('h1').text()).toEqual('Welcome, John Doe')
})

Teste com React Testing library

test('has correct welcome text', () => {
render(<Welcome firstName="John" lastName="Doe" />)
expect(screen.getByRole('heading')).toHaveTextContent('Welcome, John Doe')
})

Como você pode ver, os testes são bastante semelhantes. O renderizador shallow do Enzyme não renderiza subcomponentes, então o método render do React Testing Library é mais similar ao método mount do Enzyme.

No React Testing Library, você não precisa atribuir o resultado do render a uma variável (por exemplo, wrapper). Você pode simplesmente acessar a saída renderizada chamando funções no objeto screen. Outro ponto positivo é que o React Testing Library limpa automaticamente o ambiente após cada teste, então você não precisa chamar cleanup em uma função afterEach ou beforeEach.

Outra coisa que você pode notar é getByRole que possui 'heading' como argumento. 'heading' é o papel acessível do elemento h1. Você pode aprender mais sobre eles na página de documentação de consultas. Uma das coisas que as pessoas rapidamente aprendem a amar no Testing Library é como ele incentiva você a escrever aplicações mais acessíveis (porque se não for acessível, é mais difícil testar).

Teste 2: Campos de texto devem ter valores corretos

No componente acima, os valores dos campos são inicializados com os valores props.firstName e props.lastName. Precisamos verificar se o valor está correto ou não.

Enzyme

test('has correct input value', () => {
const wrapper = shallow(<Welcome firstName="John" lastName="Doe" />)
expect(wrapper.find('input[name="firstName"]').value).toEqual('John')
expect(wrapper.find('input[name="lastName"]').value).toEqual('Doe')
})

React Testing Library

test('has correct input value', () => {
render(<Welcome firstName="John" lastName="Doe" />)
expect(screen.getByRole('form')).toHaveFormValues({
firstName: 'John',
lastName: 'Doe',
})
})

Legal! É bem simples e prático, e os testes são claros o suficiente para que não precisemos falar muito sobre eles. Algo que você pode notar é que a <form> tem um atributo role="form", mas o que é isso?

role é um dos atributos relacionados à acessibilidade recomendados para melhorar sua aplicação web para pessoas com deficiência. Alguns elementos têm valores role padrão e você não precisa defini-los, mas outros como <div> não possuem valores role padrão. Você pode usar abordagens diferentes para acessar o elemento <div>, mas recomendamos tentar acessar elementos por seu role implícito para garantir que seu componente seja acessível por pessoas com deficiência e usuários de leitores de tela. Esta seção da documentação de consultas pode ajudá-lo a entender melhor os conceitos.

Um elemento <form> deve ter um atributo name para ter um role implícito de 'form' (conforme exigido pela especificação).

O React Testing Library visa testar os componentes da forma como os usuários os utilizam. Os usuários veem botões, cabeçalhos, formulários e outros elementos por seu papel (role), não por seu id, class ou nome da tag do elemento. Portanto, ao usar o React Testing Library, você deve evitar acessar o DOM com a API document.querySelector. (Você pode usá-la em seus testes, mas não é recomendado pelas razões mencionadas neste parágrafo.)

O React Testing Library expõe algumas APIs de consulta (queries) úteis que ajudam você a acessar os elementos do componente de forma eficiente. Você pode ver a lista de consultas disponíveis aqui. Se não tiver certeza de qual consulta usar em uma determinada situação, temos uma ótima página que explica qual consulta usar, então confira!

Se ainda tiver dúvidas sobre qual consulta do React Testing Library usar, visite testing-playground.com e a extensão do Chrome Testing Playground, que visa ajudar desenvolvedores a encontrar a melhor consulta ao escrever testes. Ela também ajuda você a encontrar as melhores consultas para selecionar elementos. Permite inspecionar as hierarquias de elementos no Chrome Developer Tools e fornece sugestões de como selecioná-los, tudo enquanto incentiva boas práticas de teste.

Usando act() e wrapper.update()

Ao testar código assíncrono no Enzyme, você geralmente precisa chamar act() para executar seus testes corretamente. Ao usar o React Testing Library, você não precisa chamar act() explicitamente na maioria das vezes porque ele encapsula as chamadas de API com act() por padrão.

update() sincroniza o snapshot da árvore de componentes do Enzyme com a árvore de componentes do React, então você pode ver wrapper.update() em testes do Enzyme. O React Testing Library não possui (nem precisa de) um método similar, o que é bom para você pois significa menos coisas para gerenciar!

Simulando eventos do usuário

Há duas maneiras de simular eventos do usuário com o React Testing Library. Uma é usando a biblioteca user-event, e a outra é usando fireEvent, que está incluída no React Testing Library. O user-event na verdade é construído sobre o fireEvent (que simplesmente chama dispatchEvent no elemento dado). O user-event é geralmente recomendado porque garante que todos os eventos sejam disparados na ordem correta para interações típicas do usuário. Isso ajuda a garantir que seus testes se assemelhem à forma como seu software é realmente usado.

Para usar o módulo @testing-library/user-event, primeiro instale-o:

npm install --save-dev @testing-library/user-event @testing-library/dom

Agora você pode importá-lo em seu teste:

import userEvent from '@testing-library/user-event'

Para demonstrar como usar a biblioteca user-event, imagine que temos um componente Checkbox que exibe uma caixa de seleção (checkbox) e um rótulo associado. Queremos simular o evento de um usuário clicando na caixa de seleção:

import React from 'react'

const Checkbox = () => {
return (
<div>
<label htmlFor="checkbox">Check</label>
<input id="checkbox" type="checkbox" />
</div>
)
}

export default Checkbox

Queremos testar que quando um usuário clica no rótulo associado à caixa de seleção, a propriedade "checked" do input é definida corretamente. Vejamos como podemos escrever um teste para esse caso:

test('handles click correctly', async () => {
render(<Checkbox />)
const user = userEvent.setup()

// You can also call this method directly on userEvent,
// but using the methods from `.setup()` is recommended.
await user.click(screen.getByText('Check'))

expect(screen.getByLabelText('Check')).toBeChecked()
})

Ótimo!

Acionando métodos de classe em testes (wrapper.instance())

Como já discutimos, recomendamos não testar detalhes de implementação e coisas que os usuários não terão conhecimento. Nosso objetivo é testar e interagir com o componente mais como nossos usuários fariam.

Se seu teste usa `instance()` ou `state()`, saiba que você está testando coisas que o usuário jamais poderia saber ou se importar, afastando seus testes da confiança de que tudo funcionará quando seu usuário interagir. —
Kent C. Dodds

Se você não sabe como testar algo interno do seu componente, reflita: "O que o usuário faria para acionar este código?" Então faça seu teste replicar isso.

Como fazer renderização shallow de um componente?

Geralmente, você deve evitar simular componentes. Porém, se necessário, experimente usar o recurso de mock do Jest. Para mais detalhes, consulte o FAQ.