Introdução ao Pytest para Testes em Python

Pytest: Framework de Testes Funcional e Flexível

Pytest é uma ferramenta de teste amplamente utilizada em projetos Python, conhecida por sua simplicidade e extensibilidade. Ela permite a criação de testes unitários, funcionais e de integração de maneira eficiente.

Instalação

Para instalar o Pytest, utilize o gerenciador de pacotes pip:

pip install pytest

Escrevendo Testes

No Pytest, os testes podem ser definidos em funções ou classes. Por convenção, nomes de arquivos devem iniciar com test_, funções de teste com test_ e classes de teste com Test. Exemplo em um arquivo test_exemplo.py:

def test_soma_elementar():
    assert 3 + 4 == 7

class TestExemploClasse:
    def test_verificacao_basica(self):
        assert True

Uso de Assertivas

Pytest utiliza a instrução assert do Python para validações. Mensagens de erro personalizadas podem ser adicionadas para facilitar a depuração:

def test_operacoes_com_mensagem():
    valor = 10 * 2
    assert valor == 20, f"Esperado 20, mas obtido {valor}"
    assert "python" in ["java", "python", "c#"], "Lista deve conter 'python'"

Testando Exceções

Para verificar se uma exceção específica é lançada, utilize pytest.raises:

import pytest

def test_excecao_esperada():
    with pytest.raises(ValueError):
        int("texto_invalido")

Marcadores (Markers)

Marcadores personalizados permitem categorizar testes. Eles são aplicados com @pytest.mark.nome e, em modo estrito, devem ser registrados no arquivo pytest.ini. Para executar testes filtrados:

pytest -m "conexao and prioridade_alta"

Pulando e Esperando Falhas

Pytest oferece decorators para pular testes ou marcá-los como esperadamente falhos:

  • @pytest.skip(reason): Pula o teste incondicionalmente.
  • @pytest.skipif(condition, reason): Pula com base em uma condição.
  • @pytest.xfail(reason): Indica que o teste é esperado falhar.

Dentro do teste, funções como pytest.skip() podem ser chamadas para alterar o fluxo:

def test_cenario_condicional():
    if condicao_complexa():
        pytest.skip("Ignorando em ambientes específicos")

Executando Testes

O comando pytest suporta divesras opções de controle:

  • -q: Modo silencioso, reduzindo a saída.
  • -v: Modo verboso, mostrando detalhes de cada teste.
  • -s: Exibe saídas de print() durante a execução.
  • Executar todos os testes em um diretório: pytest diretorio/
  • Executar um módulo específico: pytest test_modulo.py
  • Filtrar testes por nome: pytest -k "teste_a or teste_b"
  • Parar após a primeira falha: pytest -x
  • Repetir testes falhos: pytest --lf
  • Listar testes sem executar: pytest --collect-only

Configuração e Limpeza de Testes

O Pytest fornece métodos para preparação e limpeza em diferentes níveis:

  • Nível de módulo: setup_module() e teardown_module()
  • Nível de classe: setup_class() e teardown_class()
  • Nível de método: setup_method() e teardown_method()

Exemplo:

def setup_module():
    print("Iniciando configuração do módulo")

def teardown_module():
    print("Limpando recursos do módulo")

class TestComSetup:
    def setup_method(self):
        self.recurso = "valor_temporario"

    def test_uso_recurso(self):
        assert self.recurso == "valor_temporario"

Fixtures Personalizadas

Fixtures encapsulam lógicas de setup e teardown, usando yield para separar as fases. Elas podem ser definidas em conftest.py para compartilhamento.

import pytest

@pytest.fixture(scope="function")
def dados_conexao():
    print("Configurando conexão")
    conexao = {"host": "localhost", "porta": 8080}
    yield conexao
    print("Fechando conexão")

def test_conexao_valida(dados_conexao):
    assert dados_conexao["porta"] == 8080

Parâmetros de fixtures incluem scope (session, package, module, class, functon) e autouse para aplicação automática.

Parametrização de Testes

Para testes orientados a dados, utilize @pytest.mark.parametrize para fornecer múltiplos cenários:

import pytest

casos_de_teste = [
    (1, 1, 2),
    (0, 0, 0),
    (-1, 2, 1),
    (10.5, 20.5, 31.0)
]

@pytest.mark.parametrize("a, b, resultado_esperado", casos_de_teste)
def test_soma_parametrizada(a, b, resultado_esperado):
    resultado_atual = a + b
    assert resultado_atual == resultado_esperado

Tags: pytest Python3 testes-unitarios framework-de-teste fixtures

Publicado em 7-25 23:49