Pular para o conteúdo principal

Testes

python3 -m pytest persona_db/tests -q # tudo
python3 -m pytest persona_db/tests/unit -q # só unitários
python3 -m pytest persona_db/tests/statistical -q
python3 -m pytest persona_db/tests -k genetics -v
python3 -m pytest persona_db/tests --cov=persona_db --cov-report=term-missing

A configuração vive em persona_db/pyproject.toml:

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-q --tb=short"

Estrutura da suíte​

DiretórioArquivosEscopo
tests/unit/test_rng, test_socio, test_genetics, test_genetics_family_geo, test_health_criminal_family, test_criminal, test_base_engines, test_validators, test_exports, test_review_regressionsMotores, validadores e exportação isolados
tests/integration/test_pipeline, test_full_generationPipeline completo, 25 domínios, determinismo ponta a ponta
tests/statistical/test_distributionsAgregados com N grande (médias, proporções, faixas)

A lista completa de casos, extraída do código, está em Referência de API → tests/.

Três categorias de asserção​

1. Determinismo​

def test_mesmo_seed_mesmo_dataset():
a = generate_all(n=20, seed=7)
b = generate_all(n=20, seed=7)
assert a == b # todos os valores e IDs, não só as contagens

2. Invariantes duras​

Propriedades que nunca podem falhar, independentemente da semente:

def test_pais_rh_negativos_so_geram_filhos_rh_negativos():
assert GeneticEngine.rh_punnett("negativo", "negativo") == {"positivo": 0.0, "negativo": 1.0}

def test_salario_respeita_piso():
assert SocioeconomicEngine.salary(rng, "fundamental", 0, "agro", True, True) >= 1200.0

3. Propriedades estatísticas​

Sobre agregados, com margens generosas para evitar testes instáveis:

def test_proporcao_de_canhotos():
canhotos = sum(1 for _ in range(2000) if engine.handedness(False, False) == "esquerda")
assert 0.07 <= canhotos / 2000 <= 0.15 # esperado ≈ 10,9%

:::tip Sempre fixe a semente Testes estatísticos com semente fixa são determinísticos — a margem existe para proteger contra recalibrações pequenas, não contra aleatoriedade real. :::

Testar um gerador novo​

from persona_db.generators import gen_42_voluntariado
from persona_db.generators.gen_00_pessoa import generate_personas
from persona_db.validators import validate_dataset

def test_dominio_novo_passa_nos_validadores():
personas = generate_personas(40, seed=7)
dataset = {"pessoa": [p for p in personas]}
dataset.update(gen_42_voluntariado.generate(personas, seed=7))
assert validate_dataset(dataset)["passed"]

Regressões​

tests/unit/test_review_regressions.py guarda casos vindos de revisões e bugs já corrigidos. Ao corrigir um defeito, acrescente ali o caso mínimo que o reproduz — é a rede de proteção contra reintroduções.

Lint e tipos​

python3 -m ruff check persona_db # obrigatório na CI
python3 -m ruff check --fix persona_db
python3 -m black persona_db # opcional (linha 100)
python3 -m mypy persona_db # opcional, não é gate na CI

ruff está configurado com line-length = 100 e target-version = "py310".

Na CI​

O workflow .github/workflows/ci.yml roda, a cada push e pull request, em Python 3.12:

- run: python -m pip install -e './persona_db[dev]'
- run: python -m pytest persona_db/tests
- run: python -m ruff check persona_db

Detalhes em CI e qualidade.