Fixtures
Las fixtures proporcionan dependencias de prueba (conexiones a bases de datos, clientes de API, datos de ejemplo) a través de la inyección de dependencias. Defínelas una vez en conftest.py e inyéctalas por nombre de parámetro.
Receta
# tests/conftest.py
import pytest
@pytest.fixture
def sample_user():
return {"id": 1, "email": "ada@example.com"}
# tests/test_users.py
def test_user_email(sample_user):
assert "@" in sample_user["email"]Cuándo usar esto:
- Múltiples pruebas comparten la misma configuración.
- Las pruebas necesitan desmontaje (cerrar conexiones, eliminar archivos temporales).
- Quieres dependencias de prueba componibles.
Ejemplo Funcional
# tests/conftest.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
@pytest.fixture(scope="session")
def engine():
eng = create_engine("sqlite:///:memory:")
yield eng
eng.dispose()
@pytest.fixture
def db_session(engine):
connection = engine.connect()
transaction = connection.begin()
session = Session(bind=connection)
yield session
session.close()
transaction.rollback()
connection.close()
@pytest.fixture
def user_factory(db_session):
def _make(email: str = "test@example.com"):
user = User(email=email)
db_session.add(user)
db_session.flush()
return user
return _makedef test_create_user(user_factory):
user = user_factory(email="ada@example.com")
assert user.id is not NoneLo que esto demuestra:
scope="session"comparte el motor entre todas las pruebas.db_sessionpor prueba se revierte para aislamiento.- La fixture de fábrica devuelve una función invocable para datos flexibles.
- Las fixtures
yieldejecutan el desmontaje después de la prueba.
Profundización
Ámbitos de Fixtures
| Ámbito | Ciclo de vida | Usar para |
|---|---|---|
| function | Una prueba | Predeterminado, la mayoría de las fixtures |
| class | Una clase de prueba | Configuración compartida de clase |
| module | Un archivo | Configuración costosa por archivo |
| session | Ejecución completa | Motor de base de datos, instancia de aplicación |
Composición de Fixtures
@pytest.fixture
def api_client(app):
return TestClient(app)api_client recibe automáticamente la fixture app.
Errores Comunes
- Desajuste de ámbito - una fixture de sesión que depende de una fixture de función. Solución: un ámbito más amplio no puede depender de uno más estrecho.
- Estado compartido mutable - un diccionario con ámbito de sesión modificado por las pruebas. Solución: ámbito de función o copia en escritura.
- Falta de desmontaje - las conexiones se filtran. Solución: usar fixtures
yieldpara la limpieza. - Errores tipográficos en nombres de fixtures - inyectado como un parámetro que pytest no reconoce. Solución: el nombre del parámetro debe coincidir exactamente con el nombre de la fixture.
- Exceso de fixtures - configuración de una línea en una fixture. Solución: línea directa para arreglos simples; usar fixture solo cuando se reutiliza.
Alternativas
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| setUp/tearDown | Estilo unittest | Proyecto pytest |
| Configuración manual en cada prueba | Casos únicos | Configuración compartida |
| Patrón de fábrica (sin fixture) | Datos simples | Necesidad de desmontaje |
Preguntas Frecuentes
¿Dónde viven las fixtures?
conftest.py en tests/ o subdirectorios. Descubierto automáticamente por pytest.
¿Qué es yield vs return?
yield habilita el código de desmontaje después de la prueba. return no tiene desmontaje.
¿Cómo uso una fixture en otra fixture?
Declárala como parámetro: def api(app): ....
¿Qué es autouse?
@pytest.fixture(autouse=True) se ejecuta para cada prueba en el ámbito sin ser solicitado.
¿Cómo anulo una fixture?
Redefínela en un subdirectorio conftest.py o usa @pytest.fixture(name="...").
¿Pueden las fixtures ser asíncronas?
Sí, con pytest-asyncio: @pytest.fixture + async def.
¿Qué es params en las fixtures?
@pytest.fixture(params=[1, 2, 3]) ejecuta la prueba una vez por valor de parámetro.
¿Cómo accedo a una fixture sin inyectarla?
request.getfixturevalue("name") dentro de una fixture o prueba.
Ámbito de sesión y aislamiento de pruebas?
Las fixtures de sesión persisten el estado. Asegúrate de que las pruebas no muten objetos compartidos.
Fixture vs fábrica?
Una fixture proporciona una instancia. Una fábrica de fixtures devuelve una función que crea instancias.
Relacionado
- Configuración de pytest - descubrimiento de conftest
- Parametrización - múltiples entradas de prueba
- Mocking y Patching - mocks de fixtures
- Pruebas de API Web - TestClient fixtures
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+.