Especialização em Sistemas com Python & POO com Type Hints • Capítulo 18


🗺️ Mapa Conceitual do Tópico

flowchart TD
    subgraph LAYERS["Arquitetura em Camadas (Separation of Concerns)"]
        PRESENTATION["1. Camada de Apresentação (UI / CLI / Rest Controller)"]
        APPLICATION["2. Camada de Aplicação (Casos de Uso & Orquestração)"]
        DOMAIN["3. Camada de Domínio Puro (Entidades, VOs & Invariantes)"]
        INFRA["4. Camada de Infraestrutura (SQLite DAO, Rede & Sockets)"]
    end

    subgraph PYTEST_ECO["Garantia de Qualidade com Pytest"]
        ASSERT["Asserções Nativas com Introspecção Mágica (assert a == b)"]
        FIXTURES["Fixtures Injetáveis (@pytest.fixture com Setup / Teardown)"]
        PARAM["Testes Parametrizados (@pytest.mark.parametrize)"]
        MOCK["Dublês de Teste e Isolamento com unittest.mock"]
    end

    subgraph AUDIT["Auditoria Contínua & Observabilidade"]
        LOGS["Logs Estruturados em JSON Datado (reports/audit.json)"]
        COVERAGE["Métricas de Cobertura de Código com pytest-cov"]
    end

    PRESENTATION --> APPLICATION
    APPLICATION --> DOMAIN
    APPLICATION --> INFRA
    INFRA -.->|Implementa Portas| DOMAIN
    PYTEST_ECO --> AUDIT

    style LAYERS fill:#ede7f6,stroke:#512da8,stroke-width:2px
    style PYTEST_ECO fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
    style AUDIT fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px

🏛️ 1. Arquitetura em Camadas e Inversão de Controle

A separação de responsabilidades em camadas assegura que as regras essenciais de negócio sobrevivam a mudanças de tecnologias de infraestrutura ou interface gráfica:

  1. Apresentação (Presentation Layer): Janelas CustomTkinter, controladores web FastAPI ou terminais CLI. Converte eventos de entrada em chamadas aos serviços de aplicação.
  2. Aplicação (Application Layer / Use Cases): Orquestra fluxos transacionais, autenticação, controle de auditoria e despacho de notificações.
  3. Domínio (Domain Layer): O núcleo da inteligência de negócio. Contém entidades puras, objetos de valor e exceções customizadas, sem dependências de frameworks externos ou bibliotecas de banco de dados.
  4. Infraestrutura (Infrastructure Layer): Implementações concretas de acesso a banco de dados (SQLite DAO), sistemas de arquivos (pathlib), clientes HTTP e filas de mensageria.

🧪 2. O Arsenal Moderno do Pytest

O pytest substituiu amplamente o módulo legado unittest por eliminar o boilerplate de classes derivadas (unittest.TestCase) e fornecer relatórios de falhas com inspeção detalhada de variáveis locais:

Recursos Canônicos do Pytest:

Recurso Sintaxe / Mecanismo Benefício Arquitetural
Asserções Simples assert expressao == esperado Elimina dezenas de métodos legados (assertEqual, assertTrue).
Fixtures Modulares @pytest.fixture Configuração reutilizável com injeção automática de dependências.
Teardown Limpo yield recurso dentro da fixture Garante limpeza de bancos e arquivos após o encerramento do teste.
Parametrização @pytest.mark.parametrize Executa a mesma lógica com matrizes extensas de entradas e saídas.
Captura de Erros with pytest.raises(TipoExcecao): Valida se regras de negócio disparam as exceções corretas.
import pytest
from decimal import Decimal

@pytest.fixture
def conta_base() -> ContaCorrente:
    """Fixture que fornece uma conta limpa para cada teste."""
    return ContaCorrente(numero="12345-6", titular="Auditoria", saldo_inicial=Decimal("1000.00"))

@pytest.mark.parametrize("saque,saldo_esperado", [
    (Decimal("100.00"), Decimal("900.00")),
    (Decimal("500.00"), Decimal("500.00")),
    (Decimal("1000.00"), Decimal("0.00")),
])
def test_saques_validos(conta_base: ContaCorrente, saque: Decimal, saldo_esperado: Decimal) -> None:
    sucesso = conta_base.sacar(saque)
    assert sucesso is True
    assert conta_base.saldo == saldo_esperado

🎭 3. Isolamento com Dublês de Teste (unittest.mock)

Testes unitários não devem tocar a rede física nem alterar bancos de dados em produção. A biblioteca padrão provê o módulo unittest.mock com as ferramentas Mock, MagicMock e @patch:

from unittest.mock import MagicMock
from decimal import Decimal

def test_servico_faturamento_com_mock() -> None:
    # Criação de um dublê de repositório sem tocar no SQLite físico
    mock_repo = MagicMock(spec=ClienteDAO)
    mock_repo.buscar_saldo.return_value = Decimal("5000.00")

    servico = FaturamentoService(repositorio=mock_repo)
    parecer = servico.processar_cobranca(id_cliente=1, valor=Decimal("200.00"))

    assert parecer.aprovado is True
    mock_repo.buscar_saldo.assert_called_once_with(1)

📊 4. Auditoria Contínua e Governança de Logs

Em conformidade com normas regulatórias como a LGPD e os critérios de auditoria contínua, sistemas corporativos devem gerar trilhas de auditoria imutáveis (Audit Trails) serializadas em JSON estruturado:

\[\text{reports/YYYY-MM-DD\_HH-MM-SS\_auditoria.json}\]
{
  "timestamp_utc": "2026-09-28T14:45:00.125Z",
  "usuario_executor": "admin.seguranca",
  "acao": "REAJUSTE_TAXA_CREDITO",
  "status_conformidade": "APROVADO",
  "payload_anterior": { "taxa": "0.025" },
  "payload_novo": { "taxa": "0.028" },
  "hash_integridade_sha256": "8f3b2a..."
}

A execução de suites de testes via pytest --cov=. em pipelines de CI/CD assegura que nenhuma regressão de código chegue ao ambiente de produção.