Introdução ao Pytest: Testes Automatizados em Python

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 pytest incluem:
  • Capcaidade de pular testes específicos.
  • Retentativa automática de testes que falharam.
  • Integração com Allure para 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 Test e não podem ter um método __init__.
  • Métodos de Teste: Devem começar com test_.

Modos de Execução de Testes

  1. 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ífica python 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 de print.
  • -v: Aumenta o detalhamento da saída, mostrando nomes de módulos, classes e métodos.
  • -vs: Combina -v e -s para uma visualização detalhada com saídas de depuração.
  • -n NUM: Executa testes em paralelo usando múltiplos threads ou processos (requer pytest-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".

  1. 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.
  1. Configuração Global via pytest.iniO arquivo pytest.ini, localizado na raiz do projeto, permite configurar o comportamento do pytest globalmente. Esta configuração tem prioridade sobre as opções passadas na linha de comando ou no código. Estrutura do pytest.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 o pytest deve 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 o pytest.ini configurado, 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 como smoke.
  • pytest -m "smoke or usermanage": Executa testes marcados como smoke OU usermanage.
  • pytest -m "not smoke": Executa todos os testes, exceto os marcados como smoke.

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.

Tags: pytest Python Testes Automatizados Automação framework

Publicado em 7-16 07:34