Parametrização
@pytest.mark.parametrize executa uma função de teste contra vários pares de entrada/saída. Uma definição de teste, saída de falha clara para cada caso.
Receita
import pytest
@pytest.mark.parametrize("input,expected", [
(2, 4),
(3, 9),
(0, 0),
])
def test_square(input, expected):
assert square(input) == expectedQuando usar isso:
- Mesma lógica testada com múltiplas entradas
- Teste de valor de limite (0, -1, máximo)
- Substituição de funções de teste copiadas e coladas
Exemplo de Trabalho
import pytest
from myapp.billing import apply_discount
from decimal import Decimal
@pytest.mark.parametrize("price,pct,expected", [
(Decimal("100"), 10, Decimal("90")),
(Decimal("100"), 0, Decimal("100")),
(Decimal("50"), 50, Decimal("25")),
(Decimal("0"), 10, Decimal("0")),
])
def test_apply_discount(price, pct, expected):
assert apply_discount(price, pct) == expected
@pytest.mark.parametrize("pct", [-1, 101, 150])
def test_invalid_discount_raises(pct):
with pytest.raises(DiscountError):
apply_discount(Decimal("100"), pct)uv run pytest tests/test_billing.py -v
# test_apply_discount[100-10-90] PASSED
# test_apply_discount[100-0-100] PASSED
# test_invalid_discount_raises[-1] PASSEDO que isso demonstra:
- Múltiplas tuplas (entrada, esperado) em um único decorador
- Cada tupla gera um teste separado com um ID descritivo
- Parametrização separada para os casos de erro
- Falhas mostram exatamente qual conjunto de parâmetros falhou
Mergulho Profundo
IDs de Teste Personalizados
@pytest.mark.parametrize("pct", [10, 20], ids=["ten-percent", "twenty-percent"])
def test_discount(pct): ...Combinando Parametrizações
@pytest.mark.parametrize("x", [1, 2])
@pytest.mark.parametrize("y", [10, 20])
def test_combo(x, y): ... # 4 execuções de testeNotas Python
# Parametrização com pytest.param para marcas
@pytest.mark.parametrize("n", [
pytest.param(0, marks=pytest.mark.xfail(reason="caso de borda zero")),
1, 2, 3,
])Armadilhas
- Muitos casos em uma única parametrização - tabela ilegível. Correção: dividir por categoria ou usar um arquivo de dados.
- Sem IDs para entradas semelhantes - difícil identificar o caso de falha. Correção: adicionar
ids=ou usar valores legíveis. - Mutação de dados de parametrização - vazamentos entre execuções. Correção: tratar valores de parametrização como imutáveis.
- Parametrização em vez de Hypothesis - perde casos de borda que você não listou. Correção: usar Hypothesis para domínios de entrada complexos.
- Combinação acidental de parametrizações - explosão do produto cartesiano. Correção: seja deliberado; 3x3x3 = 27 testes rapidamente.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Hypothesis | Grandes espaços de entrada | 3-5 casos conhecidos |
| Loop no teste | Nunca | - |
| Funções de teste separadas | Cenários não relacionados | Mesma lógica, entradas diferentes |
FAQs
Quantos casos de parametrização são muitos?
Se a tabela for difícil de ler (>15 linhas), divida ou use um fixture CSV.
Posso parametrizar fixtures?
Sim: @pytest.fixture(params=[...]).
Como pular um conjunto de parâmetros?
pytest.param(value, marks=pytest.mark.skip(reason="...")).
Como nomear casos de teste?
ids=["case1", "case2"] ou ids=lambda val: f"pct-{val}".
Posso carregar parâmetros de um arquivo?
Sim. Leia um CSV/YAML em conftest.py e passe para parametrize programaticamente.
parametrize vs params de fixture?
parametrize no teste: entradas explícitas. Parâmetros de fixture: variações de configuração compartilhadas.
Como parametrizar testes de classe?
Coloque @pytest.mark.parametrize na classe ou em cada método.
A ordem importa?
Não para a correção. A ordem afeta apenas a sequência do relatório de teste.
Posso parametrizar testes assíncronos?
Sim com pytest-asyncio. Mesmo decorador em async def test_....
Como ver todos os nomes de teste gerados?
pytest --collect-only lista todas as variantes parametrizadas.
Relacionado
- Assertions & Estrutura de Teste - layout de teste
- Testes Baseados em Propriedades - entradas generativas
- Fixtures - configuração compartilhada
- Melhores Práticas de Teste - quando parametrizar
Versões do 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+.