Fixtures
Fixtures fornecem dependências de teste - conexões de banco de dados, clientes de API, dados de exemplo - via injeção de dependência. Defina uma vez em conftest.py, injete pelo nome do parâmetro.
Receita
# 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"]Quando usar isso:
- Vários testes compartilham a mesma configuração
- Testes precisam de desmontagem (fechar conexões, excluir arquivos temporários)
- Você deseja dependências de teste compostas
Exemplo de Trabalho
# 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()
def test_create_user(user_factory):
user = user_factory(email="ada@example.com")
assert user.id is not NoneO que isso demonstra:
scope="session"compartilha o engine entre todos os testesdb_sessionpor teste reverte para isolamento- A fixture de fábrica retorna uma função de chamada para dados flexíveis
- Fixtures
yieldexecutam a desmontagem após o teste
Mergulho Profundo
Escopos de Fixture
| Escopo | Tempo de Vida | Usar para |
|---|---|---|
| function | Um teste | Padrão, a maioria das fixtures |
| class | Uma classe de teste | Configuração compartilhada de classe |
| module | Um arquivo | Configuração cara por arquivo |
| session | Execução inteira | Engine de DB, instância de app |
Compondo Fixtures
@pytest.fixture
def api_client(app):
return TestClient(app)api_client recebe automaticamente a fixture app.
Armadilhas
- Incompatibilidade de escopo - fixture de sessão dependendo de fixture de função. Correção: escopo mais amplo não pode depender de escopo mais restrito.
- Estado compartilhado mutável - dicionário com escopo de sessão modificado por testes. Correção: escopo de função ou cópia em gravação.
- Falta de desmontagem - conexões vazam. Correção: use fixtures
yieldpara limpeza. - Erros de digitação no nome da fixture - injetado como um parâmetro que o pytest não reconhece. Correção: o nome do parâmetro deve corresponder exatamente ao nome da fixture.
- Excesso de fixtures - configuração de uma linha em uma fixture. Correção: inline arranjo simples; use fixture apenas quando reutilizada.
Alternativas
| Alternativa | Usar quando | Não usar quando |
|---|---|---|
| setUp/tearDown | estilo unittest | projeto pytest |
| Configuração manual em cada teste | Casos únicos | Configuração compartilhada |
| Padrão de fábrica (sem fixture) | Dados simples | Necessidade de desmontagem |
FAQs
Onde as fixtures ficam?
conftest.py em tests/ ou subdiretórios. Descoberto automaticamente pelo pytest.
Qual a diferença entre yield e return?
yield permite código de desmontagem após o teste. return não tem desmontagem.
Como uso uma fixture em outra fixture?
Declare-a como um parâmetro: def api(app): ....
O que é autouse?
@pytest.fixture(autouse=True) executa para cada teste no escopo sem ser solicitado.
Como sobrescrevo uma fixture?
Redefina-a em um subdiretório conftest.py ou use @pytest.fixture(name="...").
Fixtures podem ser async?
Sim com pytest-asyncio: @pytest.fixture + async def.
O que são params em fixtures?
@pytest.fixture(params=[1, 2, 3]) executa o teste uma vez por valor de parâmetro.
Como acesso uma fixture sem injetar?
request.getfixturevalue("name") dentro de uma fixture ou teste.
Escopo de sessão e isolamento de teste?
Fixtures de sessão persistem o estado. Certifique-se de que os testes não modifiquem objetos compartilhados.
Fixture vs fábrica?
Fixture fornece uma instância. Uma fixture de fábrica retorna uma função que cria instâncias.
Relacionado
- Configuração do pytest - descoberta de conftest
- Parametrização - múltiplas entradas de teste
- Mocking e Patching - mocks de fixtures
- Testando APIs Web - fixtures TestClient
Versões da 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+.