kb.erickguedes.com
Python: De Noob a Hero

Testes e Debugging

Aula 9 de 10

doctest — Testes na Documentação

def soma(a, b):
    """Retorna a soma de a e b.

    >>> soma(2, 3)
    5
    >>> soma(-1, 1)
    0
    >>> soma(0, 0)
    0
    """
    return a + b

if __name__ == "__main__":
    import doctest
    doctest.testmod()

unittest

import unittest
from meu_app import soma, divide

class TestCalculadora(unittest.TestCase):

    def setUp(self):
        """Executa antes de cada teste."""
        self.dados = [1, 2, 3]

    def test_soma(self):
        self.assertEqual(soma(2, 3), 5)
        self.assertEqual(soma(-1, 1), 0)

    def test_divide(self):
        self.assertEqual(divide(10, 2), 5)
        with self.assertRaises(ValueError):
            divide(10, 0)

    def test_lista(self):
        self.assertIn(2, self.dados)
        self.assertEqual(len(self.dados), 3)

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

pytest

# Instalar: pip install pytest

# test_calc.py
def test_soma():
    assert soma(2, 3) == 5
    assert soma(-1, 1) == 0

def test_divide_por_zero():
    with pytest.raises(ValueError):
        divide(10, 0)

# Fixtures
@pytest.fixture
def dados():
    return [1, 2, 3, 4, 5]

def test_media(dados):
    assert sum(dados) / len(dados) == 3

# Parameterize
@pytest.mark.parametrize("a,b,esperado", [
    (1, 1, 2), (2, 3, 5), (0, 0, 0), (-1, 1, 0)
])
def test_soma_param(a, b, esperado):
    assert soma(a, b) == esperado
pytest                          # descobre e executa
pytest -v                       # verboso
pytest test_calc.py             # arquivo específico
pytest -k "soma"                # filtra por nome
pytest --cov=src                # cobertura
pytest -x                       # para no primeiro erro

Debugging

# pdb — Python Debugger
def processar():
    import pdb; pdb.set_trace()  # breakpoint (Python 3.7+: breakpoint())
    x = 10
    y = x * 2
    return y

# Comandos pdb:
# n (next) — próxima linha
# s (step) — entra na função
# c (continue) — continua execução
# p var — imprime variável
# l (list) — mostra código ao redor
# q (quit) — sai

# Logging
import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)

logger.debug("Detalhes de debug")
logger.info("Operação normal")
logger.warning("Algo suspeito")
logger.error("Erro ocorreu")
logger.critical("Fatal!")

Testes não são opcionais — são documentação executável. pytest é o padrão da indústria. Use breakpoint() ao invés de print() para debug.