No deesnvolvimento de sistemas, é comum encontrar falhas intermitentes (flaky tests) que ocorrem apenas sob certas condições de carga ou concorrência. Para identificar esses problemas, o ecossistema Pytest oferece ferramentas para repetir a execução de casos de teste e automatizar a preparação do ambiente de forma eficiente.
Repetição de Testes com pytest-repeat
O plugin pytest-repeat é utilizado quando precisamos executar um mesmo teste múltiplas vezes para validar sua estabilidade ou tentar reproduzir um erro ocasional.
Instalação
Para adicionar essa funcionalidade ao seu ambiente, instale o pacote via pip:
pip install pytest-repeat
Execução via Linha de Comando
A maneira mais direta de repetir testes é utilizando o argumento --count no terminal. O comando abaixo executa o arquivo de teste 10 vezes:
pytest --count=10 test_funcionalidades.py
Também é possível definir o escopo da repetição usando --repeat-scope. Por exemplo, para repetir a sessão inteira:
pytest --count=3 --repeat-scope=session testes_integracao/
Uso de Decoradores no Código
Caso prefira embutir a repetição diretamente no script, utilize o marker @pytest.mark.repeat(n). Isso elimina a necessidade de passar parâmetros via CLI para aquele teste específico.
import pytest
import time
@pytest.mark.repeat(5)
def test_validacao_timeout():
print("Verificando estabilidade do tempo de resposta...")
time.sleep(0.2)
assert True
Interrupção em Caso de Falha
Em cenários de depuração onde você deseja rodar um teste exaustivamente até que ele falhe, combine a contagem com o parâmetro -x (exit instantâneo na primeira falha):
pytest --count=500 -x test_estabilidade.py
Automação de Fixtures com o Parâmetro autouse
Fixtures são fundamentais para configurar o estado dos testes. Por padrão, o Pytest exige que você declare explicitamente quais fixtures cada teste deve usar. No entanto, em suites grandes, injetar o mesmo parâmetro em dezenas de funções torna-se repetitivo.
O parâmetro autouse=True permite que uma fixture seja executada automaticamente para todos os testes dentro de seu escopo (função, clasce, módulo ou sessão), sem a necessidade de chamá-la explicitamente.
Implementação de Fixtures Automáticas
No exemplo a seguir, definimos uma fixture de nível de módulo para configurar o banco de dados e uma de nível de função para limpar o estado antes de cada teste.
import pytest
@pytest.fixture(scope="module", autouse=True)
def setup_infraestrutura(request):
print(f"\n--- Iniciando Módulo: {request.module.__name__} ---")
print("Configurando conexão com banco de dados de teste...")
yield
print("\n--- Encerrando Módulo e liberando recursos ---")
@pytest.fixture(scope="function", autouse=True)
def reset_ambiente_teste(request):
print(f"\n[Setup] Preparando ambiente para: {request.function.__name__}")
# Lógica de limpeza ou reset aqui
yield
print(f"\n[Teardown] Limpeza concluída para: {request.function.__name__}")
def test_operacao_escrita():
print("Executando: Teste de Escrita de Dados")
def test_operacao_leitura():
print("Executando: Teste de Leitura de Dados")
Análise do Comportamento
Ao executar o código acima com o comando pytest -s, o fluxo será o seguinte:
- A fixture
setup_infraestruturaroda uma única vez no início do arquivo. - A fixture
reset_ambiente_testeroda antes e depois de cada função de teste individualmente. - Os testes
test_operacao_escritaetest_operacao_leiturasão eexcutados sem precisar receber nenhum argumento em sua assinatura.