Assertions & Test Structure
Estrutura de teste clara torna as falhas diagnosticáveis em segundos. As instruções assert simples do pytest, juntamente com o padrão arrange-act-assert, são a base de testes Python legíveis.
Receita
def test_discount_applied():
# Arrange (Organizar)
price = Decimal("100.00")
# Act (Agir)
result = apply_discount(price, pct=10)
# Assert (Verificar)
assert result == Decimal("90.00")Quando usar isso:
- Testes são difíceis de ler ou depurar
- Falhas mostram mensagens inúteis
- Revisores não conseguem identificar qual comportamento está sob teste
Exemplo Funcional
from decimal import Decimal
import pytest
from myapp.billing import apply_discount, DiscountError
class TestApplyDiscount:
def test_ten_percent_off(self):
price = Decimal("50.00")
result = apply_discount(price, pct=10)
assert result == Decimal("45.00")
def test_zero_percent_unchanged(self):
price = Decimal("50.00")
assert apply_discount(price, pct=0) == price
def test_invalid_percent_raises(self):
with pytest.raises(DiscountError, match="pct must be 0-100"):
apply_discount(Decimal("10"), pct=-1)O que isso demonstra:
- Fluxo arrange-act-assert em cada teste
- Um comportamento por função de teste
pytest.raisespara teste de exceção com correspondência de mensagem- Agrupamento em classes é opcional (pytest coleta métodos
test_*)
Mergulho Profundo
Introspecção de Asserção
O pytest reescreve assert para mostrar valores em caso de falha:
assert result == expected
# AssertionError: assert Decimal('45.00') == Decimal('50.00')Asserções Úteis
| Em vez de | Use |
|---|---|
assert x == True | assert x |
assert len(items) == 0 | assert not items |
assert type(x) == str | assert isinstance(x, str) |
pytest.raises(Error) sem argumento | pytest.raises(Error, match="...") |
Armadilhas
- Múltiplas asserções por teste - não fica claro qual falhou. Correção: um comportamento lógico por teste; dividir casos.
- Asserção sem mensagem em verificações complexas - falha opaca. Correção:
assert x in items, f"{x} not in {items}". - Testar detalhes de implementação - testes frágeis. Correção: assertar saídas e comportamento público, não chamadas internas.
- Nenhuma limpeza após o arrange - estado vaza entre testes. Correção: usar fixtures para configuração/desmontagem.
- Comparar floats com == - falhas intermitentes. Correção:
pytest.approx(3.14, rel=1e-6).
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Asserções unittest | Apenas stdlib | Você quer introspecção |
hypothesis | Verificações baseadas em propriedades | Unidades de lógica simples |
| Testes de snapshot | Estruturas de saída complexas | Unidades de lógica pura |
FAQs
O que é arrange-act-assert?
Configura os dados (arrange), chama o código sob teste (act), verifica o resultado (assert).
Devo usar classes de teste?
Opcional. Classes agrupam testes relacionados; funções são aceitáveis para módulos simples.
Como asserto exceções?
with pytest.raises(ValueError): ou pytest.raises(ValueError, func, arg).
Como comparo floats?
assert result == pytest.approx(3.14).
Posso usar assert simples?
Sim. O pytest aprimora as falhas de assert automaticamente. Não há necessidade de self.assertEqual.
Qual o tamanho ideal de um teste?
Idealmente 5-15 linhas. Se for mais longo, extraia a configuração para fixtures.
Os nomes dos testes devem descrever o comportamento?
Sim. test_discount_over_100_raises e não test_discount_3.
Como asserto warnings?
with pytest.warns(DeprecationWarning):.
E sobre assertar None?
assert result is None (identidade), não == None.
Como asserto dicts aproximados?
Compare chaves individualmente ou use pytest.approx em valores numéricos.
Relacionados
- Configuração do pytest - configuração do projeto
- Fixtures - reutilização da etapa arrange
- Parametrização - múltiplas entradas
- Melhores Práticas de Teste - convenções
Versões da Stack: Esta página foi escrita para Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.