O que pytest faz?
pytest - O framework de testes mais poderoso do Python com fixtures, parametrização, plugins e integração com frameworks como FastAPI, Django e Flask.
Visão Geral
O pytest é um framework de testes maduro e cheio de recursos para Python. Ele ajuda você a escrever testes de forma simples e escalável, desde testes unitários simples até testes funcionais complexos.
Principais Características
- Fixtures: Gerencie configurações de teste, dados e estados de forma modular e reutilizável.
- Parametrização: Execute o mesmo teste com múltiplos conjuntos de dados sem duplicação de código.
- Plugins: Estenda funcionalidades com uma vasta gama de plugins da comunidade.
- Integração: Suporte nativo para frameworks como FastAPI, Django e Flask.
- Execução Paralela: Use
pytest-xdistpara executar testes em paralelo e acelerar o feedback. - Relatórios: Gere relatórios detalhados de falhas e cobertura de código.
Instalação
pip install pytest
Para instalar plugins adicionais:
pip install pytest-django pytest-flask pytest-asyncio pytest-cov pytest-xdist
Uso Básico
Escrevendo Testes
Crie um arquivo chamado test_exemplo.py:
# test_exemplo.py
def test_soma():
assert 1 + 1 == 2
def test_string():
assert "olá".upper() == "OLÁ"
Executando Testes
pytest
O pytest descobre automaticamente arquivos e funções de teste que correspondem ao padrão test_*.py ou *_test.py.
Fixtures
Fixtures são funções que criam dados ou estados necessários para os testes. Elas são definidas com o decorador @pytest.fixture.
import pytest
@pytest.fixture
def dados_usuario():
return {"nome": "João", "email": "[email protected]"}
def test_usuario(dados_usuario):
assert dados_usuario["nome"] == "João"
Escopo de Fixtures
As fixtures podem ter diferentes escopos: function, class, module ou session.
@pytest.fixture(scope="session")
def config_banco():
# Conecta ao banco uma vez por sessão de teste
db = conectar_banco()
yield db
db.fechar()
Parametrização
Use @pytest.mark.parametrize para testar múltiplos casos com o mesmo código de teste.
import pytest
@pytest.mark.parametrize("entrada,esperado", [
(1, 2),
(2, 4),
(3, 6),
])
def test_dobro(entrada, esperado):
assert entrada * 2 == esperado
Marcadores (Marks)
Os marcadores permitem agrupar testes e aplicar comportamentos personalizados.
import pytest
@pytest.mark.slow
def test_processamento_lento():
# Teste que demora muito
pass
@pytest.mark.skip(reason="Funcionalidade não implementada ainda")
def test_futuro():
pass
@pytest.mark.xfail
def test_falha_esperada():
assert 1 == 0
Execute apenas testes lentos:
pytest -m slow
Plugins Populares
pytest-django
Integração com Django para testar modelos, views e URLs.
pip install pytest-django
@pytest.mark.django_db
def test_criar_usuario():
Usuario.objects.create(nome="Maria")
assert Usuario.objects.count() == 1
pytest-flask
Teste aplicações Flask com contexto de requisição e cliente de teste.
pip install pytest-flask
def test_pagina_inicial(client):
resposta = client.get("/")
assert resposta.status_code == 200
pytest-asyncio
Suporte para testes assíncronos com async/await.
pip install pytest-asyncio
import pytest
@pytest.mark.asyncio
async def test_requisicao_http():
async with aiohttp.ClientSession() as session:
async with session.get("https://exemplo.com") as resp:
assert resp.status == 200
pytest-cov
Gera relatórios de cobertura de código com pytest-cov.
pip install pytest-cov
pytest --cov=meu_modulo --cov-report=html
Integração com Frameworks Web
FastAPI
Use o TestClient do FastAPI com pytest para testar endpoints.
from fastapi.testclient import TestClient
from minha_aplicacao import app
client = TestClient(app)
def test_ler_item():
resposta = client.get("/items/1")
assert resposta.status_code == 200
assert resposta.json() == {"id": 1, "nome": "Item Exemplo"}
Django
Configure pytest.ini ou pyproject.toml para usar o pytest-django:
# pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = meu_projeto.settings
testpaths = tests
Flask
Use o fixture app fornecido pelo pytest-flask:
from minha_aplicacao import criar_app
@pytest.fixture
def app():
app = criar_app()
app.config["TESTING"] = True
return app
def test_pagina_inicial(client):
resposta = client.get("/")
assert b"Bem-vindo" in resposta.data
Boas Práticas
- Organização: Coloque os testes em diretórios como
tests/ou dentro do módulo com sufixo_test. - Convenções de nomenclatura: Use nomes descritivos para funções de teste (ex:
test_criar_usuario_com_email_valido). - Fixtures: Prefira fixtures a setup/teardown explícitos para melhor modularidade.
- Parametrização: Evite duplicação de código usando
parametrize. - Marcadores: Use marcadores para separar testes rápidos de lentos ou categorizar testes.
- Plugins: Aproveite plugins da comunidade para cobrir necessidades específicas.
Comandos Úteis
| Comando | Descrição |
|---|---|
pytest | Executa todos os testes descobertos |
pytest -v | Modo verboso, exibe nomes dos testes |
pytest -k "soma" | Executa testes que correspondem à expressão |
pytest -x | Para na primeira falha |
pytest --maxfail=5 | Para após 5 falhas |
pytest --tb=short | Exibe traceback resumido |
pytest -s | Mostra saída padrão (stdout) |
pytest --co | Lista marcadores disponíveis |
pytest -n auto | Executa testes em paralelo (com xdist) |