pip install pytest``pip install pytest
sudo apt install python3-pytest``sudo apt-get install python3-pytest
sudo dnf install python3-pytest``sudo dnf install python3-pytest
sudo pacman -S python-pytest``sudo pacman -S python-pytest
brew install pytest``brew install pytest
choco install pytest``choco install pytest
python -m venv venv && source venv/bin/activate && pip install pytest``python -m venv venv && source venv/bin/activate && pip install pytest
pip install pytest pytest-cov pytest-xdist pytest-mock pytest-html``pip install pytest pytest-cov pytest-sugar
pytest --version``pytest --version
pytest``pytest
pytest test_file.py``pytest test_file.py
pytest tests/``pytest test_directory/
pytest test_file.py::test_function``pytest test_file.py::test_function_name
pytest test_file.py::TestClass``pytest test_file.py::TestClassName
pytest test_file.py::TestClass::test_method``pytest test_file.py::TestClassName::test_method_name
pytest -v``pytest -v
pytest -vv``pytest -vv
pytest -q``pytest -q
Hoja de referencia de pytest¶
Instalación¶
| Plataforma | Comando |
|---|---|
| pip (Todas las plataformas) | |
| Ubuntu/Debian | |
| Fedora/RHEL | |
| Arch Linux | |
| macOS (Homebrew) | |
| Windows (Chocolatey) | |
| Entorno Virtual | |
| Con Plugins Comunes | |
| Verificar Instalación |
Comandos Básicos¶
| Comando | Descripción |
|---|---|
| Ejecutar todas las pruebas en el directorio actual y subdirectorios | |
| Ejecutar pruebas en un archivo específico | |
| Ejecutar todas las pruebas en un directorio específico | |
| Ejecutar una función de prueba específica | |
| Ejecutar todas las pruebas en una clase específica | |
| Ejecutar un método de prueba específico en una clase | |
| Ejecutar pruebas con salida detallada (mostrar nombres de pruebas) | |
| Ejecutar pruebas con salida muy detallada (mostrar detalles completos) | |
| Ejecutar pruebas en modo silencioso (salida mínima) | |
pytest -x |
Detener después del primer fallo de prueba |
pytest --maxfail=3 |
Detener después de N fallos de prueba |
pytest -k "test_user" |
Ejecutar pruebas que coincidan con la expresión de palabra clave |
pytest -k "user and not admin" |
Ejecutar pruebas que coincidan con múltiples palabras clave (lógica AND/NOT) |
pytest -m "slow" |
Ejecutar pruebas marcadas con un marcador específico |
pytest -m "not slow" |
Ejecutar pruebas excluyendo un marcador específico |
pytest --collect-only |
Mostrar qué pruebas se ejecutarían sin ejecutarlas |
pytest --lf |
Ejecutar solo pruebas que fallaron en la última ejecución (último fallido) |
pytest --ff |
Ejecutar pruebas fallidas primero, luego otras (fallidas primero) |
pytest -l |
Mostrar variables locales en trazas de error al fallar |
Uso Avanzado¶
| Comando | Descripción |
|---|---|
pytest -n auto |
Ejecutar pruebas en paralelo usando todos los núcleos de CPU disponibles (requiere pytest-xdist) |
pytest -n 4 |
Ejecutar pruebas en paralelo con 4 procesos de trabajo |
pytest --durations=10 |
Mostrar las 10 duraciones de pruebas más lentas |
pytest --durations=10 --durations-min=1.0 |
Mostrar pruebas más lentas que tarden al menos 1 segundo |
pytest --cov=myproject |
Ejecutar pruebas con informe de cobertura de código (requiere pytest-cov) |
pytest --cov=myproject --cov-report=html |
Generar informe de cobertura HTML en el directorio htmlcov/ |
pytest --cov=myproject --cov-report=term-missing |
Mostrar cobertura con números de línea faltantes en terminal |
pytest --cov=myproject --cov-fail-under=80 |
Fallar si la cobertura es inferior al 80% |
pytest --cov-branch |
Incluir análisis de cobertura de ramas |
pytest --junitxml=report.xml |
Generar informe XML de JUnit para integración de CI/CD |
pytest --html=report.html |
Generar informe de pruebas HTML (requiere pytest-html) |
pytest --pdb |
Entrar en depurador de Python (PDB) en caso de fallos de pruebas |
pytest --trace |
Entrar en PDB al inicio de cada prueba |
pytest --setup-show |
Mostrar configuración y desmontaje de fixtures durante la ejecución |
pytest --fixtures |
Listar todos los fixtures disponibles y sus docstrings |
pytest --markers |
Listar todos los marcadores registrados |
pytest --tb=short |
Usar formato de traza más corto |
pytest --tb=line |
Mostrar una línea por fallo en la traza |
pytest --tb=no |
Desactivar salida de traza |
pytest -W error::DeprecationWarning |
Tratar advertencias de deprecación como errores |
pytest --capture=no |
Desactivar captura de salida (igual que -s) |
pytest --timeout=300 |
Establecer tiempo de espera de 300 segundos por prueba (requiere pytest-timeout) |
pytest --count=3 |
Repetir cada prueba 3 veces (requiere pytest-repeat) |
pytest --random-order |
Ejecutar pruebas en orden aleatorio (requiere pytest-random-order) |
pytest -ra |
Mostrar resumen breve de pruebas para todas las pruebas (pasadas, fallidas, omitidas, etc.) |
Configuración¶
Archivo de configuración pytest.ini¶
Colocar en el directorio raíz del proyecto:
[pytest]
# Minimum pytest version required
minversion = 7.0
# Directories to search for tests
testpaths = tests
# Test file patterns
python_files = test_*.py *_test.py
# Test class patterns
python_classes = Test* *Tests
# Test function patterns
python_functions = test_*
# Default command line options
addopts =
-ra
--strict-markers
--strict-config
--verbose
--cov=myproject
--cov-report=html
--cov-report=term-missing
# Custom markers
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
integration: marks tests as integration tests
unit: marks tests as unit tests
smoke: marks tests as smoke tests
database: marks tests requiring database connection
api: marks tests for API testing
# Directories to ignore
norecursedirs = .git .tox dist build *.egg venv node_modules
# Warning filters
filterwarnings =
error
ignore::UserWarning
ignore::DeprecationWarning
# Logging configuration
log_cli = true
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)s] %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
Configuración pyproject.toml¶
Proyectos de Python modernos usando pyproject.toml:
[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--cov=myproject",
"--cov-branch",
"--cov-report=html",
"--cov-report=term-missing:skip-covered",
"--cov-fail-under=80",
]
markers = [
"slow: marks tests as slow",
"integration: integration tests",
"unit: unit tests",
"smoke: smoke tests",
]
filterwarnings = [
"error",
"ignore::UserWarning",
]
conftest.py - Fixtures compartidos¶
Colocar en el directorio raíz de pruebas para fixtures compartidos:
import pytest
# Session-scoped fixture (runs once per test session)
@pytest.fixture(scope="session")
def database():
"""Provide database connection for entire test session"""
db = create_database_connection()
yield db
db.close()
# Module-scoped fixture (runs once per test module)
@pytest.fixture(scope="module")
def api_client():
"""Provide API client for test module"""
client = APIClient()
yield client
client.cleanup()
# Function-scoped fixture (default, runs for each test)
@pytest.fixture
def sample_data():
"""Provide sample data for testing"""
return {"id": 1, "name": "Test User"}
# Autouse fixture (automatically used by all tests)
@pytest.fixture(autouse=True)
def reset_state():
"""Reset application state before each test"""
clear_cache()
yield
cleanup_resources()
# Parametrized fixture
@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def db_type(request):
"""Test with multiple database types"""
return request.param
# Configure pytest hooks
def pytest_configure(config):
"""Add custom configuration"""
config.addinivalue_line(
"markers", "custom: custom marker description"
)
Casos de Uso Comunes¶
Caso de Uso 1: Pruebas Unitarias Básicas¶
# Create test file
cat > test_calculator.py << 'EOF'
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
EOF
# Run the tests
pytest test_calculator.py -v
Caso de Uso 2: Pruebas con Fixtures```bash¶
Create test with fixtures¶
cat > test_user.py << 'EOF' import pytest
@pytest.fixture def user_data(): return {"username": "testuser", "email": "test@example.com"}
def test_user_creation(user_data): assert user_data["username"] == "testuser" assert "@" in user_data["email"] EOF
Run tests with fixture details¶
pytest test_user.py -v --setup-show
### Caso de Uso 3: Pruebas Parametrizadasbash
Create parametrized tests¶
cat > test_math.py << 'EOF' import pytest
@pytest.mark.parametrize("input,expected", [ (2, 4), (3, 9), (4, 16), (5, 25), ]) def test_square(input, expected): assert input ** 2 == expected EOF
Run parametrized tests¶
pytest test_math.py -v
### Caso de Uso 4: Pruebas de Integración con Marcadoresbash
Create tests with markers¶
cat > test_api.py << 'EOF' import pytest
@pytest.mark.unit def test_data_validation(): assert True
@pytest.mark.integration def test_api_endpoint(): # Simulated API test assert True
@pytest.mark.slow @pytest.mark.integration def test_full_workflow(): # Long-running test assert True EOF
Run only unit tests¶
pytest test_api.py -m unit -v
Run integration tests excluding slow ones¶
pytest test_api.py -m "integration and not slow" -v
### Caso de Uso 5: Generación de Informe de Coberturabash
Run tests with coverage and generate reports¶
pytest --cov=myproject --cov-report=html --cov-report=term-missing
View coverage report¶
HTML report will be in htmlcov/index.html¶
Run with coverage threshold¶
pytest --cov=myproject --cov-fail-under=80
Generate coverage badge¶
pytest --cov=myproject --cov-report=term --cov-report=html
``## Mejores Prácticastest_- **Usar nombres de pruebas descriptivos**: Nombrar pruebas contest_user_registration_with_valid_emailprefijo y describir lo que prueban (por ejemplo, )
- **Seguir el patrón AAA**: Estructurar pruebas con secciones de Arrange (preparación), Act (ejecución), Assert (verificación) para mayor claridad
- **Usar fixtures para configuración/limpieza**: Aprovechar fixtures de pytest en lugar de métodos de setup/teardown para mejor reutilización e inyección de dependencias
- **Marcar pruebas apropiadamente**: Usar marcadores (@pytest.mark.slow,@pytest.mark.integration) para categorizar pruebas y permitir ejecución selectiva
- **Mantener pruebas aisladas**: Cada prueba debe ser independiente y no depender del estado de otras pruebas; usar fixtures con ámbitos apropiados
- **Usar parametrize para pruebas similares**: En lugar de escribir múltiples pruebas similares, usar@pytest.mark.parametrizepara probar múltiples entradas
- **Configurar pytest.ini o pyproject.toml**: Establecer valores predeterminados de proyecto para descubrimiento de pruebas, marcadores y opciones de línea de comandos en archivos de configuración
- **Escribir aserciones enfocadas**: Usar aserciones simples y claras; la introspección de pytest muestra automáticamente información detallada de fallos
- **Usar conftest.py para fixtures compartidos**: Colocar fixtures reutilizables en archivosconftest.pyen los niveles de directorio apropiados
- **Ejecutar pruebas frecuentemente**: Ejecutar pruebas durante el desarrollo conpytest -x`para detenerse en el primer fallo para retroalimentación más rápida
- Monitorear cobertura de pruebas: Revisar regularmente informes de cobertura y apuntar a 80%+ de cobertura, pero enfocarse en pruebas significativas sobre porcentaje
Resolución de Problemas¶
| Problema | Solución |
|---|---|
| Pruebas no descubiertas | Asegurar que archivos coincidan con patrones: test_*.pyo *_test.py, funciones inicien con test_, clases inicien con Test |
| Errores de importación en pruebas | Añadir archivos __init__.pyvacíos en directorios de pruebas, o instalar paquete en modo editable: pip install -e . |
| Fixture no encontrado | Verificar que el fixture esté definido en el mismo archivo o conftest.py, verificar ámbito correcto, asegurar que el nombre del fixture coincida con el parámetro |
| Pruebas pasan localmente pero fallan en CI | Verificar dependencias específicas del entorno, asegurar versiones de Python consistentes, verificar todas las dependencias en requirements.txt |
| Ejecución lenta de pruebas | Usar pytest --durations=10para identificar pruebas lentas, considerar ejecución paralela conpytest -n auto, marca las pruebas lentas con@pytest.mark.slow |
| La cobertura no funciona | Instala pytest-cov:pip install pytest-cov, asegúrate de que la ruta de origen sea correcta:--cov=myproject, verifica.coveragercconfiguración |
| Marcadores no reconocidos | Registra marcadores enpytest.iniopyproject.tomlbajo[tool.pytest.ini_options], usa--strict-markerspara detectar errores tipográficos |
| PDB no funciona con captura | Usapytest -s --pdbpara deshabilitar la captura de salida, o usapytest.set_trace()en lugar depdb.set_trace() |
| Fixtures ejecutándose en orden incorrecto | Verifica el alcance del fixture (sesión > módulo > clase > función), usa@pytest.fixture(autouse=True)con cuidado, revisa la cadena de dependencias |
| Pruebas paralelas fallando | Asegúrate de que las pruebas estén aisladas y no compartan estado, verifica condiciones de carrera, usa bloqueo adecuado para recursos compartidos |
| Fugas de memoria en pruebas | Usa@pytest.fixture(scope="function")para limpieza adecuada, asegúrate de que los fixtures liberen y limpien correctamente, verifica referencias circulares |
| Advertencias saturando la salida | Configura filtros de advertencia enpytest.ini:filterwarnings = ignore::DeprecationWarning, o usa-Wbandera: |