Todos nós sabemos a importância de testes em nosso código, precisamos deles para evitar os temidos bugs e torna-lá cada vez mais escalavél. O objetivo deste post é mostrar como executar testes unitários com Jest e TypeScript de forma objetiva, clara e direta ao ponto.
Primeiros passos
Para realizarmos nossos primeiros testes com Jest precisamos de criar um projeto Node.js (ou React.js mas nesse post vamos utilizar um projeto em Node.js), para isso vamos iniciar um projeto. Gosto de criar meus projetos na area de trabalho portanto faço o seguinte ao abrir o terminal:
cd desktop
Ao acessar o terminal realizo a criação da pasta do projeto:
mkdir tests-node-jest
Agora vamos acessar a pasta:
cd tests-node-jest
e por fim vamos iniciar o projeto em Node.js:
npm init -y ou yarn init -y
Como vamos utilizar o Typescript temos que instalar o mesmo em nosso projeto:
npm install typescript -D ou yarn add typescript -D
Precisaremos também do Jest para começar a escrever nossos testes:
npm install jest -D ou yarn add jest -D
Por fim já que estamos utilizando o Typescript precisaremos instalar o pacote ts-jest e outro pacote com as tipagens do Jest:
npm install ts-jest -D ou yarn add ts-jest -D
npm install @types/jest -D ou yarn add @types/jest -D
Configuração
Antes de iniciar os testes você precisar configurar o preset. No Jest o preset é um conjunto de configurações que servem de base.Embora essas configurações sejam muito simples, o ts-jest disponibiliza um comando para criar o arquivo jest.config.js com o preset correto.
npx ts-jest config:init
Executando Testes com Jest e TypeScript
Por padrão o Jest executa todos os arquivos que ficam na pasta tests ou que tenham os trechos test
ou spec
no nome do arquivo.
Digamos que você tenha o arquivo /src/index.ts
:
export function double(x: number): number {
return x * 2;
}
export function concat(...args: string[]): string {
return args.reduce((result, param) => result + param, '');
}
Para testar essas funções basta você criar o arquivo __tests__/index.test.ts
:
import { double, concat } from '../src/index';
describe('testing index file', () => {
test('double function', () => {
expect(double(5)).toBe(10);
});
test('concat function', () => {
expect(concat('John', ' ', 'Wick')).toBe('John Wick');
});
});
Este exemplo contém um grupo de testes definido pela função describe
e dentro do grupo tem dois testes definidos com a função test. Lembrando que também é possível criar sub-grupos com a função describe
.
Dentro da função test você precisa declarar uma expectativa seguida de um matcher. Neste exemplo, expect é a expectativa e toBe é o matcher. Ou seja, você espera que o retorno de uma função (ou uma varíavel) seja igual a um determinado valor.
Para realizar os testes, execute este comando:
npx jest
Agora se algum teste falhar o Jest vai mostrar uma mensagem de erro. Como estamos utilizando Jest e TypeScript, vale destacar que inconsistências de tipos também serão apresentadas.
Aperfeiçoando seus Testes
O exemplo que mostrei é algo muito simples, mas conforme seu software cresce seus testes também crescerão e provavelmente você precisará de funcionalidades mais avançadas. O matcher mais comum é o toBe e que funciona muito bem para comparar valores primitivos, porém com o tempo você precisará de matchers mais avançados. Eu fiz uma lista com os matchers mais populares:
- toEqual - Útil para verificar objetos e suas propriedades
- toBeFalsy - Útil para verificar valores que podem ser convertidos para false por meio da coerção do JavaScript.
-
toBeTruthy - Útil para verificar valores que podem ser convertidos para
true
por meio da coerção do JavaScript. - toContain - Útil para verificar arrays com valores primitivos.
- toContainEqual - Útil para verificar arrays com objetos.
- toMatch - Útil para verificar strings e expressões regulares (Regex).
- toThrow - Útil para verificar se uma função lançou uma exceção.
Algo muito interessante sobre os matchers, é que se você usar o prefixo .not
a condição será invertida. Por exemplo:
expect(1).not.toBe(2);
Se você deseja ver todos os matchers na documentação oficial possui mais detalhes.
Testes Assíncronos com Promises
Algo muito comum em JavaScript é testar funções assícronas. Por exemplo, digamos que você tenha a seguinte função:
export function waitSeconds(seconds: number): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`waited ${seconds} seconds`);
}, seconds * 1000);
});
}
Basicamente essa é uma função que aguarda alguns segundos e retorna uma mensagem. Ela tem como parâmetro um número que represente a quantidade de segundos e retorna uma Promise.
Você pode testar isso de várias maneiras, mas eu separei quatro tipos de testes para esta função:
import { waitSeconds } from '../src/index';
describe('example of asynchronous testing', () => {
test('testing with async/await', async () => {
expect(await waitSeconds(1)).toBe('waited 1 seconds');
});
test('testing returning a promise', () => {
return expect(waitSeconds(1.5)).resolves.toBe('waited 1.5 seconds');
});
test('testing returning a promise with callback function', () => {
return waitSeconds(0.5).then((response) => {
expect(response).toBe('waited 0.5 seconds');
});
});
test('testing with callback function', (done) => {
waitSeconds(0.8).then((response) => {
expect(response).toBe('waited 0.8 seconds');
done();
});
});
});
Vale destacar que embora sejam quatro tipos diferentes de testes, o resultado deles é o mesmo e você pode escolher o que for mais conveniente para seu caso. Na documentação oficial é mencionado sobre testes assíncronos
Fontes onde pesquisei esse conteúdo:
Top comments (0)