PyTest vá além do teste unitário

Bem-vindos! Neste tutorial, exploraremos o mundo do Pytest, uma ferramenta poderosa para testes automatizados em Python.

Python Norte 2024 

@vaniltonpinheiro

Quem sou?

  • Vanilton da Thálita 💍
  • Pai do Louie 👦🏻 e Lourenzo 👶🏻
  • Cientista da Computação 🤓
  • 🎓 Especialista  em Engenharia de Software e Gestão de Pessoas
  • 👨🏻‍💻Pessoas e Processos na @fpf.tech 😃
  • 👨🏻‍🏫 Professor na @etech

Cadastre-se para vagas

Agenda 

  1. O que precisa saber de Pytest
  2. Reaproveite o seu trabalho
  3. Expandindo o Pytest
  4. Conclusões e Boas Práticas

 

O que precisa saber de

o que é?

O Pytest é um framework de teste para Python, conhecido por sua simplicidade e flexibilidade. Sua estrutura intuitiva facilita a criação de testes, e sua ampla gama de recursos permite testar diferentes aspectos do código, desde funções individuais até integrações complexas.

 

Benefícios

Antes de tudo...

Pytest requer: Python 3.8+

Instalação: pip install pytest

Requisito para teste

class ContaBancaria:
  
    def __int__(self, saldo_inicial=0):
        self.saldo = saldo_inicial

    def depositar(self, valor):
        limite_deposito = 5000
        if valor <= 0:
            raise ValueError("O valor do depósito deve ser positivo.")
        if valor > limite_deposito:
            raise ValueError(f"O valor máximo para o depósito é {limite_deposito}.")
        self.saldo += valor
        return self.saldo

Prática

Teste unitário

import pytest
from banco import ContaBancaria


def test_deposito_valido():
    conta = ContaBancaria()
    conta.saldo = 100
    saldo_atualizado = conta.depositar(50)
    assert saldo_atualizado == 150

Reaproveite o seu trabalho

Fixtures: Reutilização de Código

 

Preparo de Ambientes

Fixtures permitem a inicialização de recursos, como conexões com bancos de dados, antes de cada teste.

Reutilização de Código

A reutilização de código através de fixtures garante consistência e simplifica a escrita de testes.

Melhoria Legibilidade

Organiza o código de teste, separando a lógica de setup e a lógica de teste propriamente dita.

Fixture

import pytest


class Music:

    def __init__(self, nome):
        self.nome = nome

    def __eq__(self, outra):
        return self.nome == outra.nome

      
class TestMusic:

    @pytest.fixture
    def minha_musica(self):
        return Music("Black")

    @pytest.fixture
    def playlist(minha_musica):
        return [Music("Numb"), minha_musica]

    def test_minha_musica_na_playlist(self, playlist):
        assert Music('Numb') in playlist

Parametrização: Testando Várias Entradas

Teste parametrizado

def deposito_values():
    return [(100, 50, 150), (0, 5000, 5000), (0, 1, 1)]
  
@pytest.mark.parametrize("saldo, entrada, expectativa", deposito_values())
def test_deposito_valido_parametrizado(saldo, entrada, expectativa, setUp):
    conta = setUp
    conta.saldo = saldo
    saldo_atualizado = conta.depositar(entrada)
    assert saldo_atualizado == expectativa

Markers: Agrupando e Categorizando Testes

Marcadores

#pytest.ini
[pytest]
markers =
    slow: marks tests as slow (deselect with '-m "not slow"')
    critical: marks tests as critical

Executando testes marcados

# Executando uma categoria
pytest -m "slow" 

# Executando teste de duas categorias 
pytest -m "slow or parametrize" 

# Executando teste que atendam apenas todas categorias definidas
pytest -m "slow and parametrize" 


# Executando por exclusão
pytest -m "not slow" 

Expandindo o Pytest

Para Cobertura e Paralelismo

Instalação: pip install pytest-cov

      pip install pytest-xdist

Cobertura de Teste

# Teste via CLI
pytest --cov=. 

# Execução e resultado em HTML
pytest --cov=. --cov-report html

Testes em paralelo

# Execução em paralela
#Com -n auto, o pytest-xdist usará quantos núcleos físicos da CPU existirem em seu computador.
pytest -n auto


# Execução definindo os núcleos
pytest -n 2 

Para Performance

Instalação: pip install pytest-benchmark

                      pip install pygal  

Testes de Performance - Padrão

def test_deposito_valido_bench(self, setUp, benchmark):
    conta = setUp
    conta.saldo = 100
    saldo_atualizado = benchmark.pedantic(conta.depositar, args=(50,), iterations=50, rounds=100)
    assert saldo_atualizado > 150
# Executando o teste
pytest --benchmark-only test_banco.py

Testes de Performance - Definindo  Iterações

# Exemplo CLI
pytest --benchmark-only --benchmark-min-rounds=10

# Exemplo script
def test_deposito_valido_bench(self, setUp, benchmark):
    conta = setUp
    conta.saldo = 100
    saldo_atualizado = benchmark.pedantic(conta.depositar, args=(50,), iterations=50, rounds=100)
    assert saldo_atualizado > 150
# Salvando o resultado da execução
pytest --benchmark-only --benchmark-save=result_bench

# Comparar a última execução com a atual
pytest --benchmark-compare  

Testes de Performance - Resultado

# Exemplo script
def test_deposito_valido_bench(self, setUp, benchmark):
    conta = setUp
    conta.saldo = 100
    saldo_atualizado = benchmark.pedantic(conta.depositar, args=(50,), iterations=50, rounds=100)
    assert saldo_atualizado > 150
# Gerando o resultado HTML
pytest-benchmark compare --histogram result_bench

Para Funcional

Instalação: pip install pytest-playwright

                      playwright install chromium

Testes Funcional

pip install --upgrade pip
pip install playwright
playwright install
# Gerando o resultado HTML
pytest-benchmark compare --histogram result_bench

Reportando resultados

Instalação: pip install pytest-html

Relatório de Testes

# Resultado dos testes em HTML
pytest --html=report.html

Outras integrações

Integrações com CI/CD

Conclusões e Boas Práticas

Referências

  1. https://pypi.org/project/pytest-benchmark/
  2. https://docs.pytest.org/en/stable/getting-started.html
  3. https://pytest-html.readthedocs.io/en/latest/
  4. https://playwright.dev/python/docs/test-runners

PyTest vá além do teste unitário

Bem-vindos! Neste tutorial, exploraremos o mundo do Pytest, uma ferramenta poderosa para testes automatizados em Python.

Python Norte 2024