Pular para conteúdo

Testes e qualidade local

A suíte que o CI roda 🔒

O check obrigatório qualidade roda exatamente isto. Verde na sua máquina = verde no CI.

ruff check .
ruff format --check .
mypy app
pytest

O CI também confere que o Alembic tem uma head só e que o PR de tarefa não traz migration (Banco).

npm run check

É lint → format:check → typecheck → test:run, na ordem do CI. O CI ainda roda npm run build no fim, porque só o build exercita o bundling do Vite.

Rode a suíte antes de abrir o PR, não depois que o CI falhar: cada empurrão para consertar o CI é uma notificação para quem revisa.

Os hooks locais

Instalados no Primeiro dia. Eles barram o problema antes de ele sair da sua máquina — mas --no-verify passa por cima, e por isso o CI existe.

Repo No commit No push
backend (pre-commit) ruff (com --fix), ruff format, mypy --strict, espaço no fim da linha, chave privada nome da branch
frontend (husky + lint-staged) eslint --fix e prettier --write nos arquivos alterados nome da branch

O mypy do hook não é o mesmo do seu .venv

O hook de commit roda o mypy num ambiente isolado, com dependências e argumentos próprios (--strict, e também nos testes). Já aconteceu de mypy app passar no .venv e o commit ser barrado logo depois. Para reproduzir o hook:

pre-commit run mypy --all-files

Princípio

Teste existe para falhar no lugar certo. Se um teste de rota quebra quando muda uma regra de negócio, ele está no nível errado — e quando quebrar, ninguém vai saber onde olhar.

Backend ✅

tests/domains/<domínio>/, um arquivo por camada. A suíte não fala com o banco: as camadas se testam com dublês, que é o que a separação de camadas compra.

Arquivo Testa Com
test_service.py regra de negócio e casos de borda repository falso em memória (FakeUserRepository)
test_router.py contrato: status, formato da resposta, validação de entrada service falso
test_models.py colunas, constraints, defaults declarados o model, sem sessão
test_repository.py o que o repository faz além de repassar (ex.: traduzir IntegrityError) sessão dublê

O molde é tests/domains/users/test_service.py. Repare na docstring do módulo: ela diz o que o teste prova e o que não prova. É um hábito do time que vale copiar.

E query e agregação?

Mock de query não testa GROUP BY. Quando chegar o primeiro domínio de agregação (dashboards, relatorios), o teste do repository vai precisar de banco de verdade — e isso ainda não existe na suíte. 🟡 Ver Em consolidação.

pytest tests/domains/users -q        # um domínio
pytest tests/test_arquitetura.py -q  # só as regras de camada

Frontend ✅

Coisa Como testar
Slice reducers e transições de status, direto, sem render
View render + interação com user-event, sem espiar o estado interno
Api com a rede mockada — não testa o backend
Formulário vazio mostra erro, válido envia uma vez, 409 cai no campo (Formulários)

O teste fica ao lado do arquivo testado: LoginView.tsx e LoginView.test.tsx.

npm run test          # modo watch, enquanto desenvolve
npm run test:run      # uma vez, como o CI

O mínimo por tarefa

  • caso feliz;
  • pelo menos um caso de borda: vazio, nulo, limite;
  • bug corrigido: o teste que falha sem a correção. Escreva o teste, veja vermelho, depois corrija.

Dado de teste

Sintético, sempre. Nunca dado real de pessoa — em fixture, seed, snapshot ou print de tela no PR.