Como fazer seu primeiro teste unitário em 4 minutos...
#reactjs #testing-library #react #javascript #testeunitario
Table of contents
No headings in the article.
Para começar vamos entender o que é o Testing Library. Bom para simplificar é uma biblioteca voltada para testes unitários de aplicações frontend. Link da biblioteca: https://testing-library.com/
Show! Agora vamos começar pois temos 4 minutos...rs
1) Primeiro passo é ter um projeto react, então vamos criar um básico.
Separe uma pasta onde vamos criar nosso projeto Abra o terminal nessa pasta e digite o comando abaixo npx create-react-app my-app (my-app é o nome do seu projeto) Abra a pasta gerada pelo comando no terminal com: cd my-app Rode o projeto digitando o seguinte comando no terminal: npm run start
2) Bom demais, nesses comando conseguimos ter um projeto react rodando e ainda já deixar instalado a biblioteca testing-library. Caso queira instalar em algum projeto existente basta fazer os passos abaixo:
npm install --save-dev @testing-library/react
OBS: com --save deixamos documentado no package.json o que instalamos para quem clonar nosso repositório conseguir rodar sem problemas, o -dev é por que utilizamos essa lib(biblioteca) somente para testar em ambiente de desenvolvimento e não queremos que afete o pacote gerado para deploy em produção! ;-)
3) Agora vamos fazer nosso primeiro teste:
Crie um arquivo no seu projeto no mesmo lugar que estiver o arquivo que deseja testar com o nome do component/arquivo, ex: button.test.jsx OBS: Usamos .test quando é um arquivo de testes completos dos comportamento do componente e vamos fazer um regressivo mesmo. E quando queremos apenas fazer uma documentação/especificação do componente usamos .spec, ou seja, fazemos um arquivo desses quando queremos testar apenas o básico e seguindo muitas vezes as premissas que fizeram criar o componente.
Então vamos mostrar nosso componente e estudar o que pode ser testado:
import React from "react";
import PropTypes from "prop-types";
import cs from "classnames";
import './Button.scss';
const Button = ({ kind, gtmCategory, gtmAction, gtmLabel, onClick, className, children, ...otherProps }) => {
return <button
onClick={onClick}
{...otherProps}
className={cs(`button ${className}`, kind ? `button--${kind}` : null)}
data-gtm-event-category={gtmCategory}
data-gtm-event-action={gtmAction}
data-gtm-event-label={gtmLabel}
>
{children}
</button>
};
Button.propTypes = {
onClick: PropTypes.func,
children: PropTypes.any,
kind: PropTypes.any,
gtmCategory: PropTypes.any,
gtmAction: PropTypes.any,
gtmLabel: PropTypes.any,
otherProps: PropTypes.any
};
export default Button;
Então vamos para nosso teste:
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import Button from './Button';
test('render button', () => {
const { getByText } = render(<Button>TESTE 1</Button>);
const linkElement = getByText('TESTE 1');
expect(linkElement).toBeInTheDocument();
});
test('render button with kind', () => {
const { getByText } = render(<Button kind="disabled">TESTE 2</Button>);
const linkElement = getByText('TESTE 2');
expect(linkElement).toBeInTheDocument();
});
Algumas explicações sobre nossos testes: Fizemos primeiro um render básico do nosso componente passando nenhuma props. Nesse teste dizemos o render do componente na linha 6, utilizando uma das facilidades da lib testing-library pois ela permite pesquisar no código renderizado um text especifico, que no nosso caso foi o título do botão.
Então para testar mesmo nosso primeiro render esperamos que encontrasse nosso titulo do botão na tela renderizada, utilizando o expect, na linha 8. Nesse caso o expect é uma das ferramentas do próprio Jest(lib que cuida dos testes).
No segundo teste fizemos uso de uma variação de layout que nosso componente permitia, passando uma props a mais e vendo se conseguimos pegar mesmo assim o título do mesmo.
Agora se perguntarmos se esses testes estão cobrindo todo nosso componente o que você diria? Se você disse não então prestou atenção no nosso código e viu que temos também uma ação no nosso botão e não passamos por ela, abaixo vamos escrever esse teste juntos:
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import Button from './Button';
test('render button', () => {
const { getByText } = render(<Button>TESTE 1</Button>);
const linkElement = getByText('TESTE 1');
expect(linkElement).toBeInTheDocument();
});
test('render button with kind', () => {
const { getByText } = render(<Button kind="disabled">TESTE 2</Button>);
const linkElement = getByText('TESTE 2');
expect(linkElement).toBeInTheDocument();
});
test('render and click button', () => {
const mockFunction = jest.fn();
const { getByText } = render(
<Button kind="disabled" onClick={()=>mockFunction()}>TESTE 2</Button>
);
fireEvent.click(getByText('TESTE 2'));
expect(mockFunction).toBeCalled();
})
Nesse último teste fizemos uma function mocada usando jest.fn() que simula uma function e contabiliza quando é acionada, assim fica fácil de testarmos o que esperamos. Basicamente renderizamos nosso botão, depois usamos o fireEvent para disparar um click no botão e usamos no expect a nossa function mocada que nos informa se foi acionada ou não, e então temos nosso resultado esperado com o toBeCalled, ou seja, essa function foi acionada? simm
Com isso terminamos o básico de um teste de componente, seguindo algumas coisas básicas e muito utilizadas em todos testes...
ahh caso queira ver o quanto que cobrimos nosso componente basta executar esse comando no terminal: npm run coverage
Então vai ser gerado uma pasta na raiz do seu projeto com o nome coverage e então basta abrir a pasta dentro e abrir no navegador o index.html, ai vai ter uma amostra de coberturas de todos seus componentes e telas. Nesse caso ficou assim o do nosso componente: