Configuración de pytest
pytest descubre y ejecuta pruebas por convención; no se requieren clases de prueba repetitivas. Un directorio tests/, un bloque de configuración pyproject.toml y uv add --group dev pytest son suficientes para empezar.
Receta
uv add --group dev pytest
mkdir tests[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]uv run pytestCuándo usar esto:
- Al iniciar pruebas en un nuevo proyecto Python
- Al migrar de
unittesta pytest - Al configurar el descubrimiento de pruebas para el diseño
src/
Ejemplo de trabajo
myapp/
├── pyproject.toml
├── src/myapp/core.py
└── tests/
├── conftest.py
└── test_core.py
# tests/test_core.py
from myapp.core import add
def test_add():
assert add(2, 3) == 5[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
addopts = "-ra -q"
filterwarnings = ["error"]uv run pytest -v
uv run pytest tests/test_core.py::test_addLo que esto demuestra:
- Las pruebas residen en
tests/, nombradastest_*.py pythonpath = ["src"]permite importar sin instalación editable en configuraciones sencillasconftest.pycontiene fixtures compartidosaddoptsestablece indicadores CLI predeterminados para cada ejecución
Profundización
Reglas de descubrimiento
- Archivos:
test_*.pyo*_test.py - Funciones:
test_* - Clases:
Test*(sin__init__) - Los plugins extienden el descubrimiento (por ejemplo,
pytest-asynciopara pruebas asíncronas)
Ubicaciones de configuración
| Archivo | Prioridad |
|---|---|
pyproject.toml [tool.pytest.ini_options] | Preferido |
pytest.ini | Legado |
Hooks de conftest.py | Por directorio |
Errores comunes
- Pruebas en la raíz del proyecto - recopiladas accidentalmente. Solución:
testpaths = ["tests"]limita el descubrimiento. - Errores de importación sin
srcen la ruta -ModuleNotFoundError. Solución:pythonpath = ["src"]opip install -e .. - Ejecución de pytest sin dependencias de desarrollo -
pytest: command not found. Solución:uv sync --group devouv run pytest. - Fixtures duplicados en
conftest.py- colisiones de nombres entre directorios. Solución: definir el alcance de los fixtures cuidadosamente; usar nombres únicos. - Advertencias como ruido - problemas reales ocultos. Solución:
filterwarnings = ["error"]para fallar ante advertencias inesperadas.
Alternativas
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| unittest | Solo stdlib, sin dependencias | Quieres fixtures y plugins |
| nose2 | Migración de legado de nose | Proyectos nuevos |
| behave | Pruebas de aceptación BDD | Pruebas unitarias/de integración |
Preguntas frecuentes
¿Dónde van las pruebas?
tests/ en la raíz del proyecto es la convención. Refleja la estructura de src/ dentro de él.
¿Necesito __init__.py en tests/?
No para pytest 7+. Un tests/ vacío sin __init__.py funciona correctamente.
¿Cómo ejecuto una sola prueba?
pytest tests/test_core.py::test_add o pytest -k "add".
¿Qué es conftest.py?
Fixtures y hooks compartidos. Se carga automáticamente desde el directorio de pruebas hasta la raíz.
¿Cómo omito una prueba?
@pytest.mark.skip(reason="...") o @pytest.mark.skipif(condition, reason="...").
¿Puede pytest ejecutar pruebas de unittest?
Sí. pytest recopila subclases de unittest.TestCase automáticamente.
¿Cómo veo la salida de print?
pytest -s deshabilita la captura de salida.
¿Qué es addopts?
Argumentos CLI predeterminados que se aplican a cada invocación de pytest.
¿Cómo configuro marcadores?
markers = ["slow: marca pruebas lentas"] en la configuración; registra todos los marcadores personalizados.
¿pytest o unittest?
pytest para proyectos nuevos. Fixtures más ricos, plugins y menos código repetitivo.
Relacionado
- Aserciones y Estructura de Pruebas - escritura de buenas pruebas
- Fixtures - configuración y limpieza
- Cobertura e Informes - medición del alcance de las pruebas
- Mejores Prácticas de Pruebas - convenciones de equipo
Versiones de la pila: 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+.