Parametrización
@pytest.mark.parametrize ejecuta una función de prueba contra muchos pares de entrada/salida. Una definición de prueba, salida de error clara por caso.
Receta
import pytest
@pytest.mark.parametrize("input,expected", [
(2, 4),
(3, 9),
(0, 0),
])
def test_square(input, expected):
assert square(input) == expectedCuándo usar esto:
- Misma lógica probada con múltiples entradas
- Pruebas de valores límite (0, -1, máximo)
- Reemplazo de funciones de prueba copiadas y pegadas
Ejemplo de funcionamiento
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] PASSEDLo que esto demuestra:
- Múltiples tuplas (entrada, esperado) en un decorador
- Cada tupla genera una prueba separada con un ID descriptivo
- Parametrización separada para los casos de error
- Los fallos muestran exactamente qué conjunto de parámetros falló
Análisis en profundidad
IDs de prueba personalizados
@pytest.mark.parametrize("pct", [10, 20], ids=["ten-percent", "twenty-percent"])
def test_discount(pct): ...Combinación de Parametrización
@pytest.mark.parametrize("x", [1, 2])
@pytest.mark.parametrize("y", [10, 20])
def test_combo(x, y): ... # 4 ejecuciones de pruebaNotas de Python
# Parametrizar con pytest.param para marcas
@pytest.mark.parametrize("n", [
pytest.param(0, marks=pytest.mark.xfail(reason="caso límite cero")),
1, 2, 3,
])Trampas comunes
- Demasiados casos en una parametrización - tabla ilegible. Solución: dividir por categoría o usar un archivo de datos.
- Sin IDs en entradas similares - difícil identificar el caso de fallo. Solución: añadir
ids=o usar valores legibles. - Mutación de datos de parametrización - fugas entre ejecuciones. Solución: tratar los valores de parametrización como inmutables.
- Parametrización en lugar de Hypothesis - omite casos límite que no has listado. Solución: usar Hypothesis para dominios de entrada complejos.
- Combinación accidental de parametrizaciones - explosión del producto cartesiano. Solución: ser deliberado; 3x3x3 = 27 pruebas rápidamente.
Alternativas
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| Hypothesis | Grandes espacios de entrada | 3-5 casos conocidos |
| Bucle en la prueba | Nunca | - |
| Funciones de prueba separadas | Escenarios no relacionados | Misma lógica, entradas diferentes |
Preguntas frecuentes
¿Cuántos casos de parametrización son demasiados?
Si la tabla es difícil de leer (>15 filas), divídela o usa una fixture CSV.
¿Puedo parametrizar fixtures?
Sí: @pytest.fixture(params=[...]).
¿Cómo omito un conjunto de parámetros?
pytest.param(value, marks=pytest.mark.skip(reason="...")).
¿Cómo nombro los casos de prueba?
ids=["case1", "case2"] o ids=lambda val: f"pct-{val}".
¿Puedo cargar parámetros desde un archivo?
Sí. Lee un CSV/YAML en conftest.py y pásalo a parametrizar programáticamente.
parametrize vs params de fixture?
parametrize en la prueba: entradas explícitas. Parámetros de fixture: variaciones de configuración compartidas.
¿Cómo parametrizar pruebas de clase?
Pon @pytest.mark.parametrize en la clase o en cada método.
¿El orden importa?
No para la corrección. El orden solo afecta la secuencia del informe de pruebas.
¿Puedo parametrizar pruebas asíncronas?
Sí con pytest-asyncio. El mismo decorador en async def test_....
¿Cómo veo todos los nombres de prueba generados?
pytest --collect-only lista cada variante parametrizada.
Relacionado
- Assertions y Estructura de Pruebas - diseño de pruebas
- Pruebas Basadas en Propiedades - entradas generativas
- Fixtures - configuración compartida
- Mejores Prácticas de Pruebas - cuándo parametrizar
Versiones de Stack: Esta página fue 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+, y uv 0.6+.