Skip to content

Instantly share code, notes, and snippets.

@renatoapcosta
Last active October 2, 2022 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renatoapcosta/d8a94fe1e66604c5c7719249aaac321b to your computer and use it in GitHub Desktop.
Save renatoapcosta/d8a94fe1e66604c5c7719249aaac321b to your computer and use it in GitHub Desktop.
Jest

Jest

Jest é um framework de teste unitário de código aberto em JavaScript criado pelo Facebook a partir do framework Jasmine.

Fundamentos de teste

Cobertura (ou coverage)

A cobertura de testes indica quais partes de seu código estão sendo executadas.

Se temos um código de 10 linhas e uma cobertura de 50%, isso quer dizer que apenas metade das linhas desse código, ou seja, 5 linhas estão sendo executadas ao longo dos testes.

Algumas ferramentas geram alguns relatórios visuais em HTML ou no terminal.

----------|----------|----------|----------|----------|-------------------|

File % Stmts % Branch % Funcs % Lines Uncovered Line #s
All files 100 100 100 100
data.js 100 100 100 100
---------- ---------- ---------- ---------- ---------- -------------------

Arquivo (ou file): todos arquivos que foram testados

Declarações (ou statements/stmts): indica se declaração como variáveis e imports foram ou não cobertos

Ramificações (ou branch): se trechos como blocos if/else, switch/case ou ternários foram executadas

Funções (ou functions/funcs): indica se as funções do seu código foram executadas

Linhas (ou lines): indica quantas linhas do código estão cobertas

Linhas não cobertas (ou uncovered lines): indica quantas linhas do código não estão cobertas

Suítes de teste (ou test suites)

Suítes de teste é um termo utilizado pra exemplificar um agrupamento de testes.

Temos uma estrutura opcional, describe que é exclusivamente para realizar um agrupamento mais específico de testes relacionados.

Teste

Para realizar um teste usamos a função test ou o seu apelido it

describe('Calculadora', () => {
  it('Soma', () => {

  });
  // ou com test
  test('Soma', () => {

  });
});

Asserções (ou assertions)

Asserção significa afirmação. É com as asserções que iremos afirmar o comportamento esperado do nosso código.

Podemos pensar na utilização das asserções em duas partes:

  • valor atual (ou de entrada/esperado);

  • valor a ser comparado (ou de saída/resultado).

Usamos a função expect para fazer uma asserção

Hooks

Outra estrutura que as ferramentas que o jest disponibiliza

Podemos utilizar as funções:

beforeAll: para executar algo antes de todos os testes;

afterAll: para executar algo após todos os testes finalizarem;

beforeEach: para executar algo antes de cada um dos testes;

afterEach: para executar algo após cada um dos testes executarem.

Arquivos para executar o teste

É comum que alguns arquivos de teste sejam escritos dentro de um diretório como __test__ ou então com o sufixo .test ou .spec (que quer dizer especificação).

Instalando o Jest

npm init -y

npm i -D jest 

package.json

{
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "jest": "^29.0.0"
  }
}

Exemplo

desconto1.js

function freteGratis (valor) {
    return valor >= 150
}

module.exports = { freteGratis }

desconto1.test.js ou desconto.spec.js

describe('Desconto 1', () => {

    const desconto1 = require('./desconto1')
    const freteGratis = desconto1.freteGratis
    
    test('Frete Gratis maior que 150', () => {
        expect(freteGratis(151)).toBeTruthy()
    })
})

Executar os testes

npm test ou npx jest

Configuração

Podemos configurar algumas opções do jest:

npx jest --init

Ele vai gerar o arquivo:

jest.config.js

module.exports = {
  clearMocks: true,
  collectCoverage: true,
  coverageDirectory: "coverage"
};

Apartir de agora ele irá mostrar o relatorio de cobertura de testes, pois irá pegar nossa configuração.

Podemos executar um teste em uma pasta especifica:

npx jest ./src

ou colocar em nosso arquivo de configuração jest.config.js a seguinte linha:

"roots": ["./src", "./src1"],

Em conjunto podemos determinar quais tipos de arquivos restringimos o nosso testes:

"testMatch": ["**/*.spec.js"]

Assim em qualquer pasta que tem um arquivo terminado com spec.js será executado o test.

Para pegar uma pasta em especificas e seus subdiretorios:

"testMatch": ["**/src/**/*.spec.js"]

Podemos ver mais detalhes dos teste usando npx jest --verbose

Jest com Typescript

Vamos instalar o typescript e um pacote de tipagem para o jest, @types/jest e ts-jest

npm i -D typescript @types/node jest ts-jest @types/jest

npx tsc --init

Vai ser instalado as versões:

"@types/jest": "^28.1.8",
"jest": "^28.1.3",
"ts-jest": "^28.0.8",

Precisamos configurar o preset no jest.config.js

module.exports = {
  preset: 'ts-jest',
};

A versão "jest": "^29.0.0", do jest não funciona mais com o ts-jest

Preset do swc da vercel

Para rodar os testes teriamos que compilar o typescript para javascript.

Vamos utilizar uma ferramenta da Vercel construida em Rust que faz a compilação de typescript para javascript.

npm i -D @swc/jest @swc/core

Modificar o jest.config.ts para fazer transformações, toda vez que ele encontrar um arquivo typescript e vai aplicar swc para fazer a compilação:

jest.config.js

module.exports = {
  transform: {
    "^.+\\.ts?$": ["@swc/jest"]
  }
};

podemos ter um arquivo typescript para configurar o jest:

jest.config.ts

export default {
 transform: {
   "^.+\\.ts?$": ["@swc/jest"]
 }
}

Exemplo:

export default {
  roots: ['<rootDir>/src'],
  clearMocks: true,
  collectCoverage: true,
  collectCoverageFrom: ['<rootDir>/src/**/*.ts'],
  coverageDirectory: "coverage",
  testEnvironment: 'node',
  transform: {
    "^.+\\.ts$": ["@swc/jest"]
  }
}

Mas neste caso precisamos colocar a lib ts-node

npm i -D ts-node

npx jest

Lista de matchers

Os matchers podem ser do tipo:

Comuns: usados para testar igualdade de valores de forma exata;

Veracidade: usados para distinguir de forma explícita entre undefined, null e false;

Number: usados para comparar números equivalentes;

String: usados para verificar expressões regulares;

Arrays e iteráveis: usados para verificar a inclusão de um item em um array ou iterável;

Exceções: usado para testar se uma função lança um erro quando chamada;

Clique aqui, para acessar a lista completa de matchers.

Assertivas

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.

Visual Code

Podemos instalar um plugin jest runner da firsttris para rodar os testes automaticamente

spyOn vs jest.fn()

Duas funções para “simular” chamadas a outras funções: spyOn() e jest.fn(). Mas existe alguma diferença teórica entre elas? Posso usar tanto uma quanto outra?

Como vimos, chamamos de mocking o processo de “substituir” (ou criar “dublês”) módulos. Substituímos a implementação original destes módulos por código que podemos testar - normalmente objetos que retornam dados úteis para os nossos testes.

Isso foi feito de duas formas durante o curso, substituindo o retorno da função com jest.fn() e chamando a função com spyOn(). Então qual a diferença?

Podemos utilizar jest.fn() quando a implementação original da função - ou seja, o código que ela executa - não é importante para o teste, e pode ser substituída pelo que definimos durante o teste, normalmente retornando um objeto.

E por que a implementação não é importante, ou em que casos isso ocorre? Por exemplo, quando o módulo que estamos testando em nossos testes unitários executa internamente uma outra função. Por se tratar de um teste unitário de nosso código, muitas vezes não temos interesse neste momento em saber da execução de outra função interna, especialmente quando se trata de bibliotecas ou módulos externos ao nosso código.

No caso de jest.spyOn(), não há substituição da implementação original da função e queremos testar se, por exemplo, a função está sendo “chamada”, se está recebendo determinado parâmetro, etc. Nesse caso, apenas executar a função com jest.spyOn() ainda vai executar a função “original” e o código dentro dela. Porém, também é possível “mocar” (ou seja, substituir a implementação original de uma função).

Para ver todos os métodos do Jest relativo a mock de funções, você pode consultar a lista na documentação oficial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment