Por que escrever testes automatizados se eu mesmo posso testar?

Node.js 10 de Dez de 2018

Hoje o assunto é sobre testes automatizados, então lá vai uma pequena historinha da minha vida profissional. Antes de mergulhar no node.js pela Rocketseat ♥️ eu programava Python, e como amante do desenvolvimento Web utilizava o Django, um framework famoso para isso, e com ele construi um sistema de gerenciamento de atividades de alunos e professores.

O sistema funcionava, mas com alguns bugs que passavam aqui e ali e eram sempre corrigidos, eu já tinha ouvido falar de testes automatizados, mas o que é um teste automatizado se eu mesmo posso ir lá e testar manualmente? Funcionou, envelopa e manda para a produção.

Esse é o primeiro erro na construção de um sistema, isso porque você não tem garantia que todas funcionalidades estarão sempre funcionando em harmonia. No sistema citado acima, ocorreu uma atualização de versão do Django e foi o suficiente para quebrar a aplicação.

O fato mais dramático é que eu fui descobrir que ela estava quebrada em produção, mas só depois de uma semana. Ocorreu que o problema não estava ao ligar o servidor, e sim em funcionalidades que eram executadas em suas diversas páginas.

Era só ter testado!

Esse é o ponto chave do post, eu devia ter aberto cada página e testado as principais funcionalidades do sistema, mas como fazer isso com um aplicativo grande? Páginas só para alunos, páginas só para professor, páginas para monitores, coordenadores e por ai vai...

Temos a prática só de testar aquilo que estamos fazendo, funcionou? Que venha a próxima feature. Mas, como eu disse: era só ter testado!!! É neste ponto entra os testes automatizados, basicamente você faz com que um software teste o seu software.

O ponto positivo é que os softwares são pragmáticos e eles vão testar sempre aquilo que você pedir para testar. O ponto negativo é que você vai ter que programar isso rs.

Software, testando software?

Não se assuste!!!
No final das contas é apenas programação.
Vou te mostrar um pouquinho como você programa seu teste.

Para isso vamos precisar de duas coisas, alguma coisa para testar e outra coisa para ser testada. Essa é a função que será testada:

module.exports = function operacoes(a, b, operador) {
  if (!/[+\-*/]/.test(operador))
    throw Error(`Operador '${operador}' inesperado`);
  return eval(`${a} ${operador} ${b}`);
};

É uma função simples que espera 3 parâmetros, dois números e um operador. E agora começa ficar divertido, testar essa nossa função.

const { assert } = require("chai");
const operacoes = require("./");

assert.equal(operacoes(1, 2, "+"), 3);
assert.equal(operacoes(1, 2, "*"), 2);
assert.equal(operacoes(1, 2, "/"), 0.5);
assert.equal(operacoes(1, 2, "-"), -1);

assert.throws(() => operacoes(1, 2, "a"), Error, "Operador 'a' inesperado");

A primeira coisa que fizemos foi importar do chai o assert, que trás consigo diversas maneiras de testar, sempre afirmando aquilo que é o teste.

No primeiro teste, é esperado que o retorno da função operacoes seja igual a 3, já que 1 + 2 = 3.

Observe que você não está querendo provar que 1 + 2 é igual a 3, mas que o retorno da sua função para aqueles argumentos tem que obrigatoriamente ser 3. Os 3 próximos testes tem os mesmos objetivos, seguindo a matemática, de afirmar o resultado do retorno da função testada com o valor passado.

O último teste vai um pouco além, ele quer dar a certeza de que ao você colocar um operador que não seja + - * / a função lança uma exceção Error e a mensagem é obrigatoriamente: Operador '<operador>' inesperado.

O que mudou?

Aparentemente o que mudou foi ter que escrever mais código. Se antes você tinha o código de uma função, agora você tem código a mais, o que naturalmente demanda mais tempo e esforço, visto que a prática de testar não é tão trivial.

Por outro lado, você ganha mais segurança e maturidade no seu código e isso pode evitar dor de cabeça no futuro. Os testes acima confirmam o formato que a sua função sempre funcionará. Se no futuro você precisar utiliza-la com um operador diferente, e criar um novo teste para uma feature que utiliza a função operacoes, em um teste de alguns segundos você descobriria o problema e corrigiria a função (operacoes) e o teste dela de forma rápida e indolor.

O que testar?

Essa é uma pergunta difícil de responder. Poderia ser tudo, mas não precisa... todavia uma direção a ser tomada é começar testando funções sensíveis/importantes do seu software, funções que possam ser utilizadas diversas vezes ou mesmo de diversas formas. Com o tempo será mais natural saber o que devemos ou que não testar.

assert.equal('Conclusão', true)

Esse foi um pequeno exemplo de um código que nunca usaríamos, mas tenha em mente que testar seus código é SEMPRE uma boa ideia.

Outra coisa importante é que o que fizemos foi apenas usar funções que testam, mas você pode utilizar um framework para agrupar, organizar e facilitar seus testes como o Mocha ou o Jasmine.

No React a dica é usar o Enzyme para ajudar nos testes, já no AdonisJS você pode olhar aqui.

Talvez, você se pergunte como testar uma página?
Você pode verificar o status do cabeçalho, se o retorno contém o json esperado, enfim existe diversas maneiras... isso requer um pouco da nossa criatividade.

Espero que você tenha gostado deste post e se interessado mais pelo assunto. Não deixe de compartilhar com os amigos e comentar ali embaixo.

Até mais guys!!

Marcadores