Módulo 15 - Testes automatizados

Testes com unittest

11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Montar uma classe de testes herdando de unittest.TestCase.
  • Escrever métodos test_ e usar self.assertEqual e companhia.
  • Rodar a suíte e ler o relatório de passou, falhou e erro.
  • Entender por que cada método de teste roda isolado dos outros.

Uma classe de testes

Asserts soltos resolvem o começo, mas logo você quer mais: agrupar testes relacionados, saber quantos passaram, ver todos os que falharam de uma vez em vez de parar no primeiro. É para isso que existe um framework de testes, e o Python já traz um na biblioteca padrão, o unittest. Não precisa instalar nada. A ideia é escrever uma classe que herda de unittest.TestCase e, dentro dela, um método para cada teste, sempre com o nome começando em test_. Esse prefixo é como o unittest descobre o que rodar.

import unittest


def dobro(n):
    return n * 2


class TestDobro(unittest.TestCase):
    def test_positivo(self):
        self.assertEqual(dobro(5), 10)

    def test_zero(self):
        self.assertEqual(dobro(0), 0)

    def test_negativo(self):
        self.assertEqual(dobro(-3), -6)


if __name__ == "__main__":
    unittest.main()

Uma classe TestCase com três testes independentes para a função dobro.

Salve esse arquivo como test_dobro.py e rode com python test_dobro.py no terminal. Em vez de usar o assert cru, cada teste chama self.assertEqual, que faz a mesma comparação de igualdade, mas de um jeito que o framework entende. Quando um assertEqual falha, o unittest não só avisa: ele mostra os dois valores, o obtido e o esperado, sem você precisar escrever a mensagem à mão. E o mais importante, ele roda todos os testes, não para no primeiro que falha.

Lendo o relatório

Quando tudo passa, o unittest imprime um ponto para cada teste e um OK no final. É a versão organizada do silêncio do assert: um resumo curto dizendo que a suíte está verde. Veja a saída dos três testes acima, todos passando.

# python test_dobro.py
# Saida:
# ...
# ----------------------------------------------------------------------
# Ran 3 tests in 0.000s
#
# OK

Três pontos, um por teste, e o OK final: os três passaram.

Agora imagine que a função dobro foi quebrada, devolvendo n + 2. O teste test_positivo, que espera 10, vai receber 7 e falhar. O unittest troca o ponto por um F naquele teste, continua os outros e, no fim, mostra um bloco explicando exatamente o que falhou, com o valor obtido e o esperado lado a lado. Não é preciso adivinhar nada.

# Com dobro quebrado (n + 2):
# Saida:
# F..
# ======================================================================
# FAIL: test_positivo (__main__.TestDobro.test_positivo)
# ----------------------------------------------------------------------
# AssertionError: 7 != 10
# ----------------------------------------------------------------------
# Ran 3 tests in 0.001s
#
# FAILED (failures=1)

Um F no lugar do ponto, o motivo (7 != 10) e o resumo FAILED com a contagem.

Consolidando o unittest

Um detalhe que costuma passar batido faz toda a diferença: cada método test_ roda isolado dos outros. O unittest cria uma instância nova da classe para cada teste, então uma variável que um teste altera não contamina o próximo. Isso é de propósito. Testes que dependem uns dos outros são frágeis, porque a ordem passa a importar e uma falha vira um efeito dominó difícil de entender. Ao manter cada teste independente, com suas próprias entradas e sua própria verificação, você ganha um diagnóstico limpo: quando um falha, o problema está exatamente ali, não em algo que aconteceu três testes antes. Por isso o framework separa tudo por padrão, e vale seguir essa disciplina.

Teste rápido

Em uma classe unittest.TestCase, como você verifica se dois valores são iguais?

Perguntas frequentes

Preciso instalar o unittest?
Não. O unittest faz parte da biblioteca padrão do Python, então basta importar com import unittest. É o mesmo caso de módulos como math e statistics que você viu antes: já vêm junto com a linguagem, sem pip e sem ambiente virtual.
Por que os métodos de teste precisam começar com test_?
Porque é assim que o unittest descobre o que rodar. Ele procura, dentro das classes que herdam de TestCase, todos os métodos cujo nome começa com test_ e executa cada um como um teste separado. Métodos com outros nomes são ignorados como testes, o que serve para auxiliares.
O que é aquele if __name__ == "__main__" no fim?
É o jeito de dizer rode a suíte quando este arquivo for executado diretamente. Ao chamar python test_dobro.py, a condição é verdadeira e unittest.main() descobre e roda os testes. Se o arquivo fosse importado por outro, os testes não disparariam sozinhos.
O que muda entre assertEqual e assertTrue?
assertEqual(a, b) verifica se dois valores são iguais e, ao falhar, mostra os dois. assertTrue(x) só verifica se x é verdadeiro. Prefira assertEqual quando comparar resultados, porque o relatório fica mais informativo mostrando o obtido e o esperado.
Se um teste falha, os outros deixam de rodar?
Não. Diferente de um assert solto, que para o programa no primeiro erro, o unittest roda todos os testes e depois resume quantos passaram e quantos falharam. Assim você vê de uma vez todos os problemas, em vez de corrigir um, rodar de novo e descobrir o próximo.
Como o unittest garante que um teste não interfere no outro?
Ele cria uma instância nova da classe de teste para cada método test_. Assim, o que um teste altera não vaza para o próximo. Essa independência é essencial: testes que dependem da ordem ou do estado deixado por outros são frágeis e dão diagnósticos confusos.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.