QA · Leitura de 7 min

Testes unitários: o que são e como escrever o primeiro

A menor unidade de confiança no seu código. Se você não consegue testar uma função isolada, provavelmente também não a entende por completo.

Um teste unitário é um pedaço de código que executa outro pedaço de código e verifica que o resultado é o que você esperava. Nada mais. Você pega uma função, dá a ela uma entrada conhecida, e confere que ela devolve a saída correta. Se coincide, o teste passa. Se não, ele falha e avisa você antes que um usuário o faça.

Essa é a resposta curta. A resposta útil é entender por que esse teste, o menor de todos, é a base sobre a qual tudo o mais se apoia. Chama se "unitário" porque examina uma unidade: a menor peça do seu programa que faz sentido testar em separado, quase sempre uma função ou um método.

01 · a baseO que é um teste unitário e o que o torna "unidade"

Pense na pirâmide de testes, um modelo que organiza os tipos de teste por quantidade e velocidade. Na base vão muitos testes unitários: rápidos, baratos, isolados. No meio, menos testes de integração, que verificam se várias peças se encaixam. E no topo, poucos testes de ponta a ponta, que percorrem o sistema completo como uma pessoa faria. A forma de pirâmide não é decorativa: ela diz quantos testes de cada tipo convém ter. Martin Fowler popularizou essa figura a partir do trabalho de Mike Cohn [1].

O que torna um teste unitário uma "unidade" é o isolamento. Ele testa uma única coisa, sem depender do banco de dados, sem chamar a rede, sem tocar no relógio do sistema nem ler um arquivo. Se o seu teste precisa de tudo isso para rodar, ele já não é unitário: é de integração, e pertence a outro nível da pirâmide.

Se você não consegue testar uma função sem ligar meia aplicação, o problema não é o teste: é o desenho da função.

Essa restrição tem um efeito colateral valioso. Escrever o teste obriga você a raciocinar sobre o que a função recebe, o que devolve e do que depende. Uma função difícil de testar costuma ser uma função que faz demais, ou que esconde dependências. O teste unitário é, sem querer, um detector de mau desenho.

Figura 1 · la pirámide de pruebas
E2E Integração Unitários muitos · rápidos · baratos poucos · lentos · caros
Quanto mais embaixo, mais testes convém ter: são rápidos e isolados. Quanto mais em cima, menos, porque são lentos e frágeis. A base larga sustenta tudo o mais.

02 · o padrãoArrange, act, assert: a anatomia de todo teste

Quase todo teste unitário bem escrito tem três partes, sempre na mesma ordem. Em inglês é conhecido como AAA: arrange, act, assert. Em português: preparar, agir, afirmar.

Preparar (arrange). Você monta o cenário: cria os dados de entrada e qualquer objeto de que a função precise. Agir (act). Você chama a função que quer testar, uma única vez, com esses dados. Afirmar (assert). Você compara o que ela devolveu com o que você esperava. Se não coincide, o teste falha.

Vejamos o exemplo mínimo. Suponha uma função que soma dois números. O teste se lê quase como uma frase.

Figura 2 · una prueba unitaria en sus tres actos
1 · PREPARAR a = 2 b = 3 esperado = 5 2 · AGIR resultado = somar(a, b) 3 · AFIRMAR assert resultado == esperado
Três blocos, um único caminho. Você prepara a entrada, chama a função uma vez, e afirma o resultado. Se a afirmação é falsa, o teste grita.

Esse assert é o coração. Uma afirmação que diz, sem ambiguidade, o que tem de ser verdade. Quando a função quebrar no futuro, porque alguém a mexeu sem querer, essa linha será a que dispara o alarme. Um bom teste unitário tem idealmente uma afirmação clara: testa uma coisa e dá um motivo concreto quando falha.

Um teste que nunca falha não prova nada

O erro de principiante é escrever um teste que passa sempre, mesmo com a função quebrada. Antes de confiar em um teste, quebre o de propósito: mude a função para que dê um resultado incorreto e confirme que o teste falha. Se ele continua passando em verde com a função avariada, o seu teste está olhando para o lado errado.

03 · o valorPor que são rápidos, baratos e a primeira linha de defesa

Um teste unitário roda em milissegundos porque não toca em nada externo. Você pode ter milhares e executá los todos em segundos, cada vez que salva uma mudança. Esse ciclo curtíssimo é o que os torna baratos: o custo de escrever um é baixo, e o custo de executá lo é quase zero. Kent Beck construiu o desenvolvimento guiado por testes justamente sobre essa ideia, escrever o teste antes do código para que o desenho nasça já verificado [2].

O valor não está em um teste, mas em tê los todos rodando juntos. Quando você muda uma função e sem querer quebra outra a dez arquivos de distância, o teste dessa outra função falha na hora. Você fica sabendo em segundos, não em produção. Isso é uma rede de segurança, e é o que permite modificar código com confiança em vez de com medo.

Sem testes unitários, cada mudança é uma aposta. Com eles, é uma hipótese que se verifica no instante.

A ISTQB, o organismo internacional de certificação de testes, situa o teste unitário como o primeiro nível de teste, o mais próximo do código e o que executam quem o escreve [3]. Não é por acaso que seja o primeiro: quanto antes se pega um defeito, mais barato sai corrigi lo. Uma falha detectada por um teste unitário custa minutos; a mesma falha descoberta por um cliente custa reputação.

Há um limite honesto que convém dizer. Os testes unitários verificam que cada peça funciona em separado, mas não que o sistema completo funciona junto. Você pode ter cem funções perfeitas que, montadas, fazem algo incorreto. Para isso existem os outros níveis da pirâmide. O teste unitário não é toda a qualidade: é a sua base. E uma base sólida é a condição para que tudo o que vai em cima se sustente.

Comece pelo pequeno. Pegue a função mais simples que você tiver, uma que receba algo e devolva algo, e escreva a ela um teste com os três atos: prepara uma entrada, chama a, afirma a saída. Quebre a para confirmar que o teste avisa. Esse primeiro teste em verde, que roda num piscar de olhos, é a menor unidade de confiança que você pode construir sobre o seu código. Tudo o mais se apoia ali.

Fuentes

  1. Fowler, M. (2012). Test Pyramid. martinfowler.com/bliki/TestPyramid.html. (Populariza la figura a partir de Cohn, M., Succeeding with Agile, Addison-Wesley, 2009.)
  2. Beck, K. (2002). Test-Driven Development: By Example. Addison-Wesley Professional. ISBN 978-0321146533.
  3. ISTQB (International Software Testing Qualifications Board). Certified Tester Foundation Level Syllabus, sección sobre niveles de prueba (component/unit testing). istqb.org.
  4. ISO/IEC/IEEE 29119-4. Software and systems engineering. Software testing. Part 4: Test techniques. International Organization for Standardization.

Aprenda mais sobre IA

Ver tudo Aprenda IA