Jest + TypeScript para quem nunca fez testes - Qual o básico que você precisa saber?
Tags: javascript, node, testing, typescript
Published: 2020-09-12 17:27:34

Primeiramente, é interessante você entender qual a real necessidade de se realizar testes automatizados durante o desenvolvimento de alguma aplicação. 

Imagina que você está trabalhando em uma API. Você chama uma rota, passando alguns parâmetros para ela, então a rota chama um controlador que, através algumas operações xpto, te retorna uma informação. Pense nela como uma fábrica: você entra com matéria prima (request) e ela te retorna um produto (return).

A entrada da fábrica, seria a rota que chamamos, o interior da máquina, o controlador, seus componentes internos as funções e, por fim, a saída seria o response.

Assim como em uma máquina, para que uma determinada rota funcione bem, todos os seus componentes internos precisam estar funcionando corretamente: isso é, seguindo um padrão de “como funciona”.

Imagine uma linha de produção de carros. Um belo dia, você realiza uma manutenção preventiva em um robô, cujo a função era apertar os parafusos das portas. Porém, sem notar, você acaba invertendo o sentido que a parafusadeira gira… Caos resume a sua linha de produção depois disso. Você irá perder horas de trabalho, tentando entender por que raios os carros estão saindo o parafuso frouxo.

Esse caos poderia ser evitado de uma maneira muito simples: 

_ao terminar uma manutenção, teste para saber se tudo está funcionando corretamente._

Bom, voltando ao mundo do software, imagine que durante o processo de desenvolvimento, você acaba modificando uma função… Talvez uma modificação simples, que só adicione um parâmetro à saída de uma função. Será que esse parâmetro extra vai quebrar algo no seu código?

Os testes automatizados estão aí justamente para responder essa sua pergunta:com eles é possível checar, de maneira automatizada, todos os inputs e todos os outputs de pedaços do seu código, de forma que seja possível identificar problemas no seu código e corrigi-los rapidamente.

Existem diversas filosofias de desenvolvimento que implementam testes: TDD, BDD, Unit Testing, ATDD… Como esse é apenas um post introdutório, não vou me ater a elas, buscando focar mais em introduzir os novatos nesse mundo de testes.

##Passo I - Afiando o machado

Bom, irei partir do princípio de que você já tem todo um ambiente de TypeScript montado e, é claro, saiba ao menos um framework de NodeJS para construirmos algum exemplo. Eu irei utilizar o ExpressJS, por ser simples.

Primeiramente, iremos instalar as ferramentas necessárias para iniciar o trabalho

```
yarn install --D jest ts-jest @types/jest
```

Caso esteja de fato utilizando o TypeScript, é de suma importância instalar o ts-jest e os tipos do Jest.

Depois de instalado, deveremos criar um arquivo de configurações para o Jest: jest.config.js

```javascript
module.exports = {
  roots: ['<rootDir>/src'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
  moduleFileExtensions: ['ts', 'js', 'json'],
}
```

Importante:
Roots -> Aqui, você deve dizer aonde ficará o código fonte da sua aplicação. Por padrão, eu sempre crio uma pasta src dentro do projeto, para por todo código lá dentro.
testRegex -> Aqui, será o regex que o jest irá utilizar para identificar se um arquivo é, ou não é, um arquivo que contém testes. Isso, porque não dizemos ao jest qual arquivo executar. Por padrão, ele sempre irá executar todos os testes que ele conseguir achar.

Esse é um Regex “padrão”, ele irá buscar por arquivos que contenham o formato:

Nome-do-teste.test.tsx
Nome-do-teste.test.ts
Nome-do-teste.spec.tsx
nome-do-teste.spec.ts

Observe também que ele irá buscar todos esses testes dentro da pasta __tests__. Caso queira mudar, basta mudar essa sessão do Regex.

##Passo II - Criando uma função que será testada

Nossa função de testes será bastante simples, e eu irei implementá-la de uma maneira “não otimizada”, justamente para apresentar um caso de uso dos testes unitários.

A função em questão deverá receber dois arrays, então somar a somatória desses arrays.

Caso você esteja pensando “What the f*ck???” eu vou dar um exemplo prático

sumTest( [1,2,3], [4,5,6] )

sumArray( [ 1, 2, 3 ] ) + sumArray( [ 4, 5, 6 ] )

sumArray( [ 1, 2, 3 ] ) = 1 + 2 + 3 = 6  
sumArray( [ 4, 5, 6 ] ) = 4 + 5 + 6 = 15

sumArray( [ 1, 2, 3 ] ) + sumArray( [ 4, 5, 6 ] ) = 6 + 15 = 21

Logo:   
sumTest( [1,2,3], [4,5,6] ) = sumArray( [ 1, 2, 3 ] ) + sumArray( [ 4, 5, 6 ] ) = 6 + 15 = 21

Entendido o algorítimo, iremos implementá-lo da seguinte maneira:

função sumTest => recebe a,  recebe b :
retorna função sumArray => recebe a + função sumArray => recebe b

Em javascript:

```javascript
export Const sumArray = (array: Array<Number>): Number {
	Let acumulator = 0;
	Return array.map(number => acumulator + number)
}

export Const sumTest = (a: Array<Number>, b: Array<Number>): Number => {
	Return sumArray(a) + sumArray(b)
}
```

Salvaremos esse arquivo dentro de:
src/functions/sums.ts

##Passo III - Criando os testes

Bom, agora criaremos o nosso arquivo de testes para testar as funçẽs de soma.
Para isso, vamos criar ele da seguinte forma:
src/__tests__/sums.test.tsx

Inicialmente, devemos importar as funções que vamos testar para o nosso arquivo de testes

```javascript
import { sumTest, sumArray } from ‘../functions/sums.js’
```

Agora, usaremos a seguinte sintaxe:

```javascript
it(“explicação do que a função deve fazer” () => {
	// função sendo executada, e retornando para uma variável
	expect(“<variável”>).toBe(“<valor esperado>”);
});
```

Vamos supor que você queira testar a seguinte função

```javascript
const  sum = ( a, b ) => a + b
```

Sabemos que sum(1,1) deve dar 2, correto?

```javascript
it(“Deve somar os numeros 1 e 1, retornando 2” () => {
	const resultado = sum(1,1);
	expect(resultado).toBe(2);
});
```

Caso não seja, essa o jest irá acusar algum erro. Do contrário, irá passar no teste.


Ok, agora vamos voltar ao que interessa, nossas funções de soma.

sumArray => ela soma um array. Logo, sabemos que se passarmos o array [1,2], ela deverá retornar 3, correto?

```javascript
it(“Deve somar os numeros contidos no array, passados como argumento”, () => {
	Const resultado = sumArray([1,2]);
	expect(resultado).toBe(3);
});
```

sumTest => ela deve somar os itens contidos nos dois arrays, depois somar os resultados. Se passarmos [1,2] e [1,2] como argumento, ela deverá retornar 6, certo? (1 + 2) + (1 + 2)

```javascript
it(“Deve somar a somatória dos itens contidos nos dois arrays”, () => {
	Const resultado = sumTest([1,2],[1,2]);
	expect(resultado).toBe(6);
});
```

Ao executar “jest” na pasta do projeto, ambas as funções irão ser testadas e, se nenhum erro foi cometido, irão passar normalmente. Do contrário, o próprio JEST irá te mostrar aonde função quebrou, mostrando o valor que era esperado, e o valor que foi recebido.

BÔNUS - Refatorando o código sem quebrar nada.

Iremos refatorar a função sumArray de uma maneira simplificada, através da função reduce.

Como ela funciona?

A função reduce é uma função que itera um array, tal qual o map, o forEach, o filter… A diferença é que ela possui um “acumulador”, que soma nele o item atual iterado, aplicado alguma regra (ou sem regras, como é no nosso caso). Terminando a iteração, ela retorna o acumulador.

Podemos reescrever a função da seguinte forma:

```javascript
const sumArray => (array: Array<Number>): Number => 
array.reduce((i: Number, acumulator: Number) => i + acumulador); 
```
	
Depois disso, basta rodar novamente o jest e ver que nada quebrou durante os testes.


Esse foi um post curto, apenas para servir de introdução para uma série de posts a respeito de testes que irei fazer. Estudem ele e, em caso de dúvidas, pode entrar em contato comigo!

Bons estudos!