Testes unitários em React

5 Dicas para escrever bons Testes Unitários

Para garantir a qualidade de software é preciso de testes, e não há forma melhor de testar uma aplicação do que com testes, então para te ajudar a criar aplicações React com maior qualidade, hoje vou lhe mostrar como escrever testes unitários em React.

Mas afinal o que são testes de aplicação?

São trechos de códigos que visam testar a aplicação, seja trechos dela ou até a aplicação como um todo.

Como assim? Escrever código para testar meu código?

Bom, é isso mesmo.

Mas para que possamos entender melhor como funcionam os testes de frontend, vamos entender melhor os conceitos dos principais tipos de teste.

  • Testes Unitários: Buscam testar um trecho de código, são os testes “mais baratos” pois levam menos tempo para serem feitos e executados.
  • Testes de integração: Testam a integração entre componentes e/ou entre serviços (se o componente está buscando os dados do backend por exemplo), esse tipo de teste é mais caro de se construir pois levam mais tempo para serem sua criação e execução, esses testes ficam no meio da pirâmide de testes.
  • Controle de usabilidade: Já no topo da pirâmide ficam os testes de interface, ou de usabilidade, eles são bem demorados de se construir pois buscam prever as possíveis iterações do usuário com a interface, além disso por fazer essa simulação esses testes demoram muito a executar (muitas vezes horas).

Vale lembrar que para cada tipo de testes tem ferramentas específicas para auxiliar, que variam de acordo com a linguagem ou até mesmo com a biblioteca usada.

E o que é teste unitário em React?

É um código que visa testar um pedaço da aplicação, onde você tem o controle de todos os dados de entrada, para poder verificar a saída.

Para fazer isso no react usamos a renderização da árvore de componentes, assim é possível ter o controle dos dados de entrada tanto é possível validar os dados de saída.

Agora que entendemos os diferentes tipos de testes vamos entender então como funciona um teste unitário no React.

Testes unitários em React – Bibliotecas

Há muitas bibliotecas de testes para React mas eu prefiro o JEST.

O JEST é a biblioteca de testes padrão do create-react-app.

Ou seja, ele já vem instalado por padrão.

Além do React o JEST também funciona com vários outros frameworks e bibliotecas Javascript, como Node, Angular e Babel por exemplo.

Para garantir o comportamento dos componentes o JEST cria snapshots daquele componente durante a execução do teste.

Então dessa maneira é possível identificar se o comportamento esperado foi atendido ou não.

Justamente por criar tais snapshots o JEST funciona muito bem com execução paralela de testes, o que poupa muito tempo na execução.

Além disso vamos utilizar a biblioteca Enzyme para facilitar a renderização dos componentes nos testes.

Testes unitários em React -Exemplo

Iniciando o Projeto

Vamos iniciar o projeto usando o create-react-app.

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

Para conferir a instalação do projeto e rodar o primeiro teste é só rodar o comando abaixo:

npm test

Aliás esse é o comando que vamos rodar sempre que for preciso testar a aplicação.

O resultado esperado deve ser como abaixo:

Agora para instalarmos o Enzyme usamos o comando:

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

Para configurar o Enzyme vamos criar um arquivo chamado setupTest.js dentro da pasta src do projeto.

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

Após configurar o Enzyme estamos prontos para começar a criar o componente que vamos testar.

Criando o componente de exemplo

Vamos começar a partir do contexto inicial do componente.

Contexto inicial:
Criar uma tela deve exibir os dados de usuários.

Esses dados serão obtidos a partir de uma api.

Para fazer a exibição dos dados do usuário criei o componente UserList.

import React from 'react';

class UserList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }
    getUsersFromApi(){
        return fetch("https://jsonplaceholder.typicode.com/users");
    }
    getUsers(){
        this.getUsersFromApi()
        .then(res => res.json())
        .then(
            (result) => {
                this.setState({data:(result.map((user) =>
                <li key={user.id}>
                    {user.name}
                </li>
                ))});
            },
            (error) => {
                console.log("Ocorreu um erro");
            }
        )
    }
    componentWillMount(){
        this.getUsers();
    }
    render(){
        return(
            <div>
                <ul>{this.state.data}</ul>
            </div>
        );
    }
}

export default UserList;

Dentro desse componente serão buscados os dados em uma api e os exibirá os dados dos usuários em uma tabela.

Para facilitar a visualização do código eu coloquei o código no meu GitHub.

Dessa forma fica mais simples de entender os exemplos.

Escrevendo os testes

Para criarmos os testes precisamos criar primeiro um arquivo com a extensão .test.js.

Onde por convenção o nome do arquivo é o nome do componente.

Para podermos testar só a exibição da lista de usuários precisamos ter fixos os dados que serão testados.

E ai temos o nosso primeiro problema.

Os dados são obtidos através de uma API.

Então não é possível garantir o retorno.

Mesmo que a API seja sua pode haver algum problema de conexão inesperado, ou qualquer coisa parecida.

Se não conseguimos controlar o retorno da API como fazemos então?

Podemos escrever o teste de duas formas.

A primeira é criando um mock da instância do componente.

Já a segunda é inserindo os dados de teste direto no state.

Ambas são válidas mas eu prefiro o uso de mocks.

Mas por fins didáticos vou mostrar ambos os cenários.

Controle do State

No primeiro caso vou testar injetando os dados no state diretamente a partir da instância.

Após inserir os dados, forço a atualização da instância e confiro se o tamanho da lista é o esperado.

  
import React from 'react';
import UserList from './UserList';
import { shallow } from 'enzyme';
import toJson from "enzyme-to-json"

it("should render the user list", () => {
  const app = shallow(<UserList />)
  app.instance().setState({data: <li>teste</li>});
  app.instance().forceUpdate();
  // Checking output
  expect(app.find('li')).toHaveLength(1)
})

Usando Mocks

Os mocks são usados para simular as chamadas reais.

Ou seja, permite criar uma estrutura que vai emular o funcionamento das chamadas feitas pelo componente, mas que por sua vez tem seus parâmetros controlados.

No teste vamos criar um mock da função getUsersFromApi, controlando o retorno dele.

it("should render the user list using mocks", () => {
  const app = shallow(<UserList />)
  app.instance().getUsersFromApi = jest.fn();
  app.instance().getUsersFromApi.mockReturnValue([{
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "[email protected]",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  }])
  app.instance().forceUpdate();
  // Checking output
  expect(app.find('li')).toHaveLength(1)
})

Dessa forma não precisamos nos preocupar com o retorno da API, pois o retorno vai estar fixo.

Testes unitários em React – Conclusão

Como podemos ver escrever testes unitários em React é simples, mas no primeiro momento pode parecer complicado.

Mas é preciso de muita prática para se tornar cada vez mais simples.

Vale lembrar que além dos testes unitários há também os outros tipos de testes.

Além disso é possível criar testes de integração usando o JEST, para isso é só não fazermos a parte do mock.

Mas se sua aplicação ainda não tem nenhum teste, comece pelos unitários.

Eles são de longe os mais rápidos e fáceis de criar.

E já vão melhorar e muito a qualidade da sua aplicação.

E conforme sua aplicação for sendo testada você pode evoluir para as outras camadas de testes.

Tendo assim uma aplicação com a qualidade cada vez mais garantida.

Agora se você quiser aprender mais a fundo como testar aplicações Javascript eu recomendo que veja o curso Aprenda a testar Aplicações Javascript.

Quer saber mais sobre React? Clique aqui.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *