Aprender testes de unidade não para após dominar as habilidades técnicas. Tem muito mais coisas envolvidas do que só escrever testes. Você sempre deve se esforçar para alcançar o melhor retorno do tempo investido escrevendo testes de unidade, minimizando o esforço e maximizando os benefícios que eles oferecem.
Projetos que alcançam esse equilíbrio crescem sem esforço, não precisam de muita manutenção, e podem se adaptar rapidamente a mudanças.
Testes de unidade são uma técnica de teste em que as menores partes testáveis de uma aplicação, chamadas unidades, são individualmente e independentemente verificadas para validar seu comportamento correto.
Uma unidade é um “caso de uso” dentro do sistema e sempre tem um “ponto de entrada” e um “ponto de saída”. Um exemplo simples é uma função que calcula algo e retorna um valor. Vale ressaltar que uma unidade pode ser uma função, várias funções, ou até mesmo vários módulos ou componentes.
Um ponto de entrada é algo que podemos acionar de fora (via testes ou código de produção) e resulta em algo: retorna um valor, altera um estado ou faz uma chamada para algo externo.
O código abaixo mostra uma exemplo simples de unidade.
function sum(a, b) {
return a + b;
}
Nesse caso, a função é o ponto de entrada, e como a chamada da função resulta em um valor retornado, ele é o ponto de saída.
Um teste é basicamente um código que dispara um erro quando o resultado da execução é diferente do esperado. O exemplo a seguir mostra o que seria um teste sem o uso de nenhum framework.
const result = sum(6, 4);
const expected = 10;
if (result !== expected) {
throw new Error(`${result} is not equal to ${expected}`);
}
É possível adicionar mais testes com variações nos inputs usando o mesmo ponto de entrada. Para isso, provalvemente você vai querer ter métodos genéricos para usar em todos os testes.
function expect(result) {
return {
toEqual(expected) {
if (result !== expected) {
throw new Error(`${result} is not equal to ${expected}`);
}
},
};
}
function test(title, callback) {
try {
callback();
console.log(`PASSED: ${title}`);
} catch (error) {
console.error(`FAILED: ${title}`);
console.error(error);
}
}
test("sum with 6 and 4 is equal 10", () => {
const result = sum(6, 4);
expect(result).toEqual(10);
});
test("sum with 2 and 3 is equal 5", () => {
const result = sum(2, 3);
expect(result).toEqual(5);
});
Observe como os testes são fáceis de ler e escrever com apenas alguns métodos utilitários. Frameworks de teste fornecem mais métodos como esses, facilitando ainda mais a escrita de testes.