Escrevendo testes unitários em aplicações Node.js usando Mocha
Testes unitários são testes escritos junto com o desenvolvimento do código, e testam pequenas partes do código da aplicação. A execução desses testes deve ser rápida para que sejam executados com frequência. Assim, depois de qualquer mudança no código, podemos executá-los e garantir que nada quebrou.
Cada linguagem tem suas ferramentas para escrever e executar testes unitários, e este artigo mostra o básico de como implementar esses testes em uma aplicação Node.js utilizando o framework Mocha.
O que é o Mocha?
O Mocha é um framework de testes que roda em Node.js e no browser. Seu código é aberto, mantido e muito utilizado pela comunidade, com documentação extensa.
Instalando as dependências
Usaremos um projeto simples de uma calculadora para implementarmos nossos testes. O projeto inicial está neste repositório do GitHub.
O primeiro passo é instalar a dependência do Mocha através do comando abaixo. Usamos a flag -D
para que a dependência seja instalada como dependência de desenvolvimento.
npm i -D mocha
Configuração básica
Vamos criar uma pasta test
na raiz do nosso projeto, onde deixaremos os testes unitários
+-- src
| +-- operations
| | +-- add.js
| | +-- divide.js
| | +-- multiply.js
| | +-- subtract.js
+-- test
| +-- operations
No arquivo package.json
precisamos configurar nosso script de teste. Nele, executamos o comando mocha
, passando o diretório onde estarão os arquivos com nossos testes.
...
"scripts": {
"test": "mocha ./test/**/*.js",
},
...
Implementando nossos testes
Vamos começar implementado os testes para a operação de adição.
Para isso, criamos um arquivo add.spec.js
dentro de /test/operations/
.
A primeira coisa a fazer no arquivo é chamar a função describe
passando o nome da funcionalidade que estamos testando e uma função que irá conter os testes, como veremos a seguir. Esse describe
é uma função do Mocha que ajuda a estruturar nossos testes, indicando quais testes dizem respeito a quais funcionalidades.
Vamos então implementar nosso primeiro teste, usando a função it
do Mocha.
A função it
corresponde a um teste. Ela recebe uma descrição do que deve acontecer para que o teste passe e uma função onde iremos chamar a função add
e fazer nossas asserções. No exemplo, a descrição indica que quando passarmos os valores 2 e 3 para a função add
, ela deve retornar o valor 5 como resultado.
Com a estrutura montada, vamos escrever a chamada para a função e as asserções.
No exemplo acima:
- Na linha 1, estamos importando a o módulo
assert
nativo do Node.js. É com ele que faremos nossas asserções, ou seja, verificaremos se o retorno da função sob teste é igual ao resultado que esperamos. - Na linha 2 importamos a função
add
, que estamos testando. - Na linha 6, a função
add
é chamada utilizando os parâmetros de teste 2 e 3. Armazenamos o retorno em uma variávelresult
para ser verificada na linha abaixo. - Na linha 7 é verificado se o valor que a função
add
retornou é igual ao valor que esperamos, ou seja, igual a 5. Para isso usamos a função.equals()
do módulo assert, que recebe o resultado real como primeiro parâmetro e o resultado esperado como segundo parâmetro.
Com nosso teste escrito, usamos o comando npm test
para executá-lo.
Verificando lançamento de erros
Vamos utilizar a função divide
para demonstrar como podemos verificar se uma funcionalidade está lançando erros de maneira esperada.
A função divide
lançará um erro quando o divisor passado for igual a 0. Vamos testar se essa regra funciona como o esperado.
A estrutura do teste é similar a que escrevemos para a função add
, com excessão das descrições e da linha 6, onde fazemos a asserção.
Na descrição do teste, indicamos que o teste deverá lançar um erro se o divisor for igual a 0.
Na linha 6, usamos a função .throws()
do módulo assert. Aqui a asserção é diferente daquela que vimos para a função add.
Não podemos executar a função armazenando o resultado em uma variável antes da asserção, pois dessa forma não conseguiremos saber se um erro foi lançado. Temos que fazer com que a função .throws()
execute a função sob teste e avalie se o erro foi lançado.
Para que possamos passar a função divide
com os dois parâmetros necessários para dentro da asserção sem que essa função divide
seja executada, estamos envolvendo o divide(2, 0)
em uma função. Dessa forma o .throws()
irá conseguir dentro dele executar nossa função sob teste, capturando os erros lançados.
Se rodarmos novamente o comando npm test
veremos nossos resultados até agora.
Mocha e arrow functions
Repare que não utilizamos arrow functions como parâmetros nas nossas funções de describe
ou it
, pois o uso dessas funções é desencorajado devido a problemas relacionados ao escopo léxico do this
e o contexto do Mocha, que não poderia ser acessado. Caso não seja necessário acessar o contexto do Mocha os testes funcionarão, mas mesmo assim a documentação desencoraja o uso devido a refatoração que pode ser complexa caso seja necessário no futuro acessar o contexto.
Finalizando
Este artigo mostrou como implementar de maneira básica uma estrutura e testes unitários usando Mocha e o módulo assert
do Node.js. O projeto está disponível caso queira clonar e escrever o restante dos testes, ou mesmo "quebrar" o código já testado e ver o que acontece quando os teste são executados.