DEV Community

Cover image for #TesteSemNeura Desmistificando Testes Unitários com Jest
Iury Nogueira
Iury Nogueira

Posted on

#TesteSemNeura Desmistificando Testes Unitários com Jest

Bem-vindo de volta! No último artigo, conversamos sobre a importância dos testes e como eles podem ser um diferencial na nossa jornada como desenvolvedores. Hoje, daremos um passo além e mergulharemos em um aspecto mais prático e aplicado dos testes unitários, focando na ferramenta Jest. Se você ainda não leu o artigo anterior eu sugiro a leitura.

O Jest é uma das ferramentas mais populares para testes em JavaScript, não apenas simplifica o processo, mas também torna a experiência de escrever testes agradável, você pode usa-lo para testar seus códigos frontend e backend. Está preparado para elevar suas habilidades de teste e deixar o medo de lado? Então, vamos lá!

Antes de começarmos você precisa configurar o jest no seu projeto, para isso é só chamar nosso velho amigo npm, execute o comando na raiz do seu projeto.

npm install --save-dev jest
Enter fullscreen mode Exit fullscreen mode

ou execute com o Yarn:

yarn add --dev jest
Enter fullscreen mode Exit fullscreen mode

Particularmente eu gosto sempre de adicionar um novo script ao meu package.json para executar os testes, dessa forma:

"scripts": {
  "test": "jest"
}
Enter fullscreen mode Exit fullscreen mode

Agora é só executar npm run test ou yarn test.

Vamos pegar um caso bem didático para nosso primeiro teste, quero que você se atente principalmente a estrutura do teste, eu costumo escrever testes pensando sempre na seguinte ordem: O que meu teste tem que validar, preparação/processamento e o que eu espero que seja correto na saída do processamento. Vou deixar mais claro com o exemplo abaixo:

// primeiro.test.js

test('dois mais dois é igual a quatro', () => {
  expect(2 + 2).toBe(4);
});
Enter fullscreen mode Exit fullscreen mode

para executar esse teste execute:

npm test
Enter fullscreen mode Exit fullscreen mode

ou execute com o Yarn:

yarn test
Enter fullscreen mode Exit fullscreen mode

você verá essa saída no terminal indicando que seu teste passou.

Image description

note que eu procuro validar que "dois mais dois é igual a quatro", e eu espero (expect) que o resultado do processamento dessa soma seja 4 (toBe(4)). Por enquanto vamos nos atentar nisso, na estrutura de teste, o que se deve testar e o que esperar de cada teste, esse conceito é muito importante.

Vamos supor que você tenha uma função que deve recebe um valor em real (nossa moeda) e converte esse valor para dólar considerando que o dólar custa 5 reais. Vamos lá!

// conversorRealParaDolar.test.js

// Função que converte um valor de reais para dólar
function converterRealParaDolar(valor) {
  const valorDolar = 0.2;

  const valorConvertido = valor * valorDolar;
  return Number(valorConvertido.toFixed(2));
}

test('100 reais deve ser 20 dólares', () => {
  expect(converterRealParaDolar(100)).toBe(20);
});

test('deve lançar um erro para valores negativos', () => {
  expect(() => converterRealParaDolar(-100)).toThrow(
   'O valor a ser convertido deve ser um número positivo.'
  );
});
Enter fullscreen mode Exit fullscreen mode

Note que eu chamo nossa função que converte e retorna o valor em dólar, mais uma vez checo o resultado com o toBe(), também adicionei um caso que um bom QA testaria, um número negativo! Nesses casos utilizamos o toThrow para checar uma exception, sempre é importante cobrir todos os casos possíveis de entrada para sua função e mapear os casos no teste, você pode escrever mais de um caso de test para uma mesma funcionalidade. Agora execute os testes com o comando que já falei anteriormente, você verá o seguinte resultado:

Image description

O segundo caso de teste quebrou pois nossa função não lança um erro quando um número é negativo, "mas Iury, é claro que o teste vai quebrar, como tu tá testando uma coisa que não foi implementada?" Isso é o que a gente chama de TDD! Basicamente você implementa todos os casos de teste e o desafio é você ir tirando o "vermelho" dos seus testes quando for implementando a função, mas isso é assunto para outro artigo, vamos seguir somente com esse breve conceito, um "ifzinho" no nosso código resolverá esse problema.

// funcao atualizada
function converterRealParaDolar(valor) {
    const valorDolar = 0.2;

    // chique né?
    if (isNaN(valor) || valor <= 0) {
      throw new Error('O valor a ser convertido deve ser um número positivo.');
    }

    const valorConvertido = valor * valorDolar;
    return Number(valorConvertido.toFixed(2));
  }
Enter fullscreen mode Exit fullscreen mode

execute os testes novamente e veja que nosso teste passou, não é satisfatório? :)

Image description

O expect possui vários matchers, o mais comum como já usamos aqui é o toBe, outro muito comum de se usar no dia a dia é o toHaveLength onde você pode checar o tamanho de um array ou de uma string como no exemplo abaixo (repare também no not :D):

expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);
Enter fullscreen mode Exit fullscreen mode

para conferir todos os matchers sugiro que você consulte a doc

Outro aspecto fundamental nos testes unitários é a cobertura de código, no exemplo da função de conveterRealParaDoar ela está 100% coberta porque nossos testes passam por todas as linhas de código, caso o teste da exception fosse removido nós não teríamos todo nossa função validada, por isso é importante sempre manter essa cobertura alta para que tenhamos o número máximo de casos possíveis mapeados em nossos testes, isso vai te ajudar a não ter aquele medo que falamos no primeiro artigo e você vai se sentir mais a vontade para realizar mudanças no código, agora vamos configurar a coleta do coverage!

  1. Abra o arquivo de configuração do Jest (normalmente jest.config.js ou no bloco jest em seu package.json).

  2. Adicione essa configuração para habilitar a geração de cobertura:

// jest.config.js

module.exports = {
  collectCoverage: true,
  collectCoverageFrom: ['src/**/*.js'], // esse é o caminho dos seus testes,
  coverageReporters: ['json', 'lcov', 'text', 'html'], // eu gosto de adicionar o HTML porque ele cria uma página bonitinha com vários progress.
};
Enter fullscreen mode Exit fullscreen mode
  1. Só executar!
npm test --coverage
Enter fullscreen mode Exit fullscreen mode

ou execute com o Yarn:

yarn test --coverage
Enter fullscreen mode Exit fullscreen mode

Acredito que com isso nós temos nossa porta de entrada para os testes, aconselho praticar com suas funções diariamente, no próximo artigo eu vou abordar sobre TDD!

Agradeço por sua leitura até aqui e gostaria muito do seu feedback, estou comprometido para melhorar e fornecer um conteúdo útil para ajudar no desenvolvimento de vários outros devs por ai a fora. Obrigado!

Top comments (2)

Collapse
 
ami_aram profile image
Ami Aram • Edited

Eai meu senhor, como vai?

Alguns feedbacks após ler seu artigo e tentar seguir. Arquitetura de pastas, onde seria um bom lugar, arquiteturalmente falando para manter os arquivos de testes, talvez seja uma dúvida frequente pra quem tá começando no mundo de testes. Outra coisa, é que eu segui o que você falou e nenhum teste foi encontrado

Image description

e só depois eu descobri que o jest identifa os testes pelo .teste no nome do arquivo

No mais, parabéns pela iniciativa!

Collapse
 
hallef_vieira_e702fb3c6fb profile image
hallef vieira

Olá @ami_aram
Sobre a arquitetura de pastas, não há um padrão ou convenção que diga a forma mais correta de organizar esses arquivos. Porém, há muitas conversas na comunidade e práticas.
Por exemplo:
há devs que criam o arquivo de teste no mesmo lugar do arquivo que será testado, tendo o mesmo nome com o diferencial da extensão que fica .test ou .spec.
Já há outros devs que preferem concentrar esses arquivos de teste dentro de uma pasta geral chamada "tests" podendo ou não estar dentro da pasta principal do projeto "src", e dentro dessas pastas você organizar sub-pastas para concentrar testes unitários, integração e ponta-a-ponta(e2e).
Eu particularmente prefiro a segunda opção, pois visualmente agrada meus olhos ao ver as coisas menos embaraçadas.
Mas fica a sei critério como organizar, desde que lá no package.json quando você configurar os scripts de comandos para executar os testes, você especificar o caminhos dos teste certinho.

Abraço amigo!