Testes automatizados são cruciais no desenvolvimento de software. Em Python, existem várias ferramentas para isso, como unittest e pytest. O pytest se destaca pela sua flexibilidade e recursos avançados.
O que é Pytest? O pytest é um framework de testes robusto e maduro para Python, oferecendo maior flexibilidade em comparação com o unittest. Ele é amplamente utilizado para automação de testes em diversas áreas:
- Automação Web com Selenium.
- Automação de APIs com Requests.
- Automação de Aplicações Mobile com Appium. Recursos notáveis do
pytestincluem: - Capcaidade de pular testes específicos.
- Retentativa automática de testes que falharam.
- Integração com
Allurepara gerar relatórios visuais detalhados. - Facilidade de integração contínua com ferramentas como Jenkins.
- Um ecossistema rico de plugins que expandem suas funcionalidades.
Plugins Úteis do Pytest O pytest possui uma vasta gama de plugins que aprimoram o processo de teste. Alguns dos mais comuns são:
pytest-xdist: Permite a execução distribuída de testes em múltiplos núcleos de CPU.pytest-ordering: Controla a ordem de execução dos testes.pytest-rerunfailures: Tenta executar novamente os testes que falharam.pytest-html: Gera relatórios de teste em formato HTML.allure-pytest: Cria relatórios de teste esteticamente agradáveis e informativos.
Instalação de Plugins Para gerenciar a instalação de múltiplos plugins, é recomendável listar suas dependências em um arquivo requirements.txt e instalá-los em lote usando pip:
pip install -r requirements.txt
Crie um arquivo chamado requirements.txt na raiz do seu projeto e adicione os nomes dos plugins, um por linha:
pytest
pytest-xdist
pytest-ordering
pytest-rerunfailures
pytest-html
allure-pytest
Após criar o arquivo, execute a instalação pelo terminal:
pip install -r requirements.txt
Para verificar se a instalação foi bem-sucedida, execute:
pytest --version
Alternativamente, os plugins podem ser instalados individualmente:
pip install pytest
pip install pytest-xdist
pip install pytest-ordering
pip install pytest-rerunfailures
pip install pytest-html
pip install allure-pytest
Convenções de Nomenclatura e Estrutura de Testes O pytest segue convenções específicas para descobrir e executar testes:
- Arquivos de Teste: Devem começar com
test_ou terminar com_test. - Classes de Teste: Devem iniciar com
Teste não podem ter um método__init__. - Métodos de Teste: Devem começar com
test_.
Modos de Execução de Testes
- Execução via Código (Modo Principal) É possível executar testes programaticamente usando
pytest.main().
- Executar todos os testes:
python import pytest pytest.main() - Especificar um módulo:
python import pytest pytest.main(['-vs', 'test_login.py']) - Especificar um diretório:
python import pytest pytest.main(['-vs', './interface_testcase']) - Executar um teste específico usando Node ID: O Node ID é uma string que identifica unicamente um teste (formato:
modulo.py::Classe::metodo).python if __name__ == '__main__': pytest.main(['-vs', './test_cases/test_01.py::test_function']) # Executa uma função específicapython if __name__ == '__main__': pytest.main(['-vs', './test_cases/test_01.py::TestLogin::test_001']) # Executa um método de uma classe
Opções Comuns de Execução Diversas flags podem ser usadas para customizar a execução dos testes:
-s: Exibe informações de depuração, como saídas deprint.-v: Aumenta o detalhamento da saída, mostrando nomes de módulos, classes e métodos.-vs: Combina-ve-spara uma visualização detalhada com saídas de depuração.-n NUM: Executa testes em paralelo usando múltiplos threads ou processos (requerpytest-xdist). Exemplo:pytest -vs ./testcase/test_login.py -n 2.--reruns NUM: Reexecuta testes que falharam um número especificado de vezes.-x: Interrompe a execução assim que um teste falhar.--maxfail=NUM: Para a execução após um número máximo de falhas. Exemplo:pytest -vs ./test_cases/test --maxfail 2.-k EXPRESSION: Executa apenas os testes cujos nomes correspondem à expressão fornecida. Exemplo:pytest -vs ./test_cases/test_01.py -k "may".
Exemplo de Execução Paralela Sem paralelismo, um conjunto de testes pode levar mais tempo. Ao usar a flag -n, o tempo de execução é significativamente reduzido. Execução sem paralelismo: Execução com -n=2:
if __name__ == '__main__':
pytest.main(['-vs', './test_cases', '-n=2'])
Exemplo de Reexecução de Falhas
if __name__ == '__main__':
pytest.main(['-vs', './test_cases', '--reruns=2'])
Exemplo de Execução por Expressão (-k)
if __name__ == '__main__':
pytest.main(['-vs', './test_cases/test_01.py', '-k', 'may'])
O resultado mostrará apenas os testes cujos nomes contêm "may".
- Execução via Linha de Comando Você pode executar testes diretamente do terminal:
- Executar todos os testes:
pytest - Especificar um módulo:
pytest -vs test_login.py - Especificar um diretório:
pytest -vs ./interface_testcase - Especificar um teste/classe/função:
pytest -vs ./interface_testcase/test_interface.py::test_04_funcAs mesmas flags mencionadas anteriormente (-s,-v,-vs,-n,--reruns,-x,--maxfail,-k) são aplicáveis aqui. Gerando relatório HTML: Use a flag--html=./report/report.html.
- Configuração Global via
pytest.iniO arquivopytest.ini, localizado na raiz do projeto, permite configurar o comportamento dopytestglobalmente. Esta configuração tem prioridade sobre as opções passadas na linha de comando ou no código. Estrutura dopytest.ini:
[pytest]
addopts = -vs --html=./report/report.html
testpaths = ./test_cases
python_files = test_*.py
python_classes = Test*
python_functions = test
markers =
smoke: smoke tests
usermanage: user management tests
Opções comuns em pytest.ini:
addopts: Parâmetros padrão para a linha de comando.testpaths: Diretórios onde opytestdeve procurar por testes.python_files: Padrão para nomes de arquivos de teste.python_classes: Padrão para nomes de classes de teste.python_functions: Padrão para nomes de funções/métodos de teste.markers: Define marcadores personalizados para agrupar testes. Com opytest.iniconfigurado, os testes serão executados de acordo com as regras definidas, independentemente do modo de execução.
Controle da Ordem de Execução de Testes Por padrão, o pytest executa os testes na ordem em que aparecem (de cima para baixo). Para alterar essa ordem, utilize o marcador @pytest.mark.run(order=N), onde N é um número inteiro definindo a sequência.
import time
import pytest
def test_function_may():
print("Esta função é executada primeiro por padrão.")
class TestLogin:
def test_001(self):
time.sleep(5)
print("Executado após test_004.")
@pytest.mark.run(order=2)
def test_002_may(self):
assert 2 == 1 # Este teste falhará
def test_003(self):
print("Executado após test_002_may.")
@pytest.mark.run(order=1)
def test_004(self):
print("Executado antes de test_001 e test_003.")
Agrupamento e Execução de Testes por Grupos (Marcadores) O pytest permite agrupar testes usando marcadores personalizados, definidos no pytest.ini. Isso é útil para executar conjuntos específicos de testes, como "smoke tests" ou testes de um módulo específico. Defina os marcadores no pytest.ini:
[pytest]
markers =
smoke: tests de fumaça
usermanage: testes do módulo de gerenciamento de usuários
Aplique os marcadores aos seus testes:
# test_02.py
import time
import pytest
class TestLog:
def test_003(self):
time.sleep(5)
print("Execução de teste em paralelo.")
@pytest.mark.smoke
def test_chen(self):
print("Teste de fumaça.")
@pytest.mark.usermanage
def test_user(self):
print("Teste de gerenciamento de usuário.")
Execute testes por marcador:
pytest -m "smoke": Executa apenas os testes marcados comosmoke.pytest -m "smoke or usermanage": Executa testes marcados comosmokeOUusermanage.pytest -m "not smoke": Executa todos os testes, exceto os marcados comosmoke.
Ignorando Testes O pytest oferece maneiras de pular a execução de testes:
- Pular incondicionalmente: Use
@pytest.mark.skip(reason="...").python @pytest.mark.skip(reason="Este teste não será executado.") def test_chen(self): print("Ignorado.") - Pular condicionalmente: Use
@pytest.mark.skipif(condition, reason="...").python age = 18 @pytest.mark.skipif(age >= 18, reason="Idade >= 18, pulando teste.") def test_user(self): print("Executado apenas se a condição for falsa.")
Geração de Relatórios Para gerar relatórios HTML detalhados, você pode configurar o pytest.ini para incluir a opção --html:
[pytest]
addopts = -vs --html=./report/report.html
testpaths = ./test_cases
python_files = test_02.py
python_classes = Test*
python_functions = test
markers =
smoke: smoke tests
usermanage: user management tests
Após executar os testes com esta configuração, um arquivo de relatório HTML será gerado no caminho especificado (./report/report.html), fornecendo uma visão geral detalhada dos resultados dos testes.