Uma unidade por vez sem perder o todo
Nesta aula
Foco é delimitar a mudança
Uma unidade de trabalho é uma mudança pequena com fronteiras e resultado verificáveis. Ela não precisa coincidir com um arquivo. Corrigir a seleção de casos ativos pode exigir uma função e dois testes, enquanto alterar uma mensagem pode envolver o HTML e o JavaScript da página. A unidade fica pequena quando sua decisão central pode ser explicada e sua consequência pode ser observada, não quando possui arbitrariamente poucas linhas.
O risco do trabalho por unidades é encerrar cada peça isoladamente e descobrir tarde que elas discordam. O servidor pode devolver um objeto enquanto a página espera uma lista. O teste pode criar um caso válido que o arquivo real nunca permite. Integrar significa atravessar essas fronteiras com os contratos efetivos. Não significa usar informações pessoais ou dados de produção. Nossa Oficina usa dados sintéticos representativos e serviços locais reais.
Cartão de trabalho preenchido
| Campo | Unidade U-ATIVOS |
|---|---|
| Objetivo | Não revelar casos inativos no catálogo público. |
| Entrada conhecida | Arquivo data/casos.json validado. |
| Arquivos a inspecionar | src/catalogo.mjs, src/servidor.mjs, public/app.js e respectivos testes. |
| Mudança inicialmente autorizada | Seleção do catálogo e teste de regressão; ampliar escopo somente com justificativa. |
| Preservações | Formato público, estados vazio/erro, navegação por teclado e dependências externas zero. |
| Fronteiras | Arquivo para função; função para resposta HTTP; resposta para interface. |
| Conclusão | Testes aplicáveis aprovados e fluxo público observado; limites registrados. |
Inspecionar não é autorização automática para alterar. A lista permite compreender os consumidores antes da mudança. Se o formato da resposta precisar mudar, a unidade deixa de ser uma correção local: é necessário atualizar explicitamente os consumidores e os testes de contrato.
Como atravessar as fronteiras
- Confirme o estado anterior e registre a versão que será modificada. Execute a validação atual para não atribuir falhas antigas à nova mudança.
- Teste a regra em memória com um ativo e um inativo. Esse teste rápido localiza problemas na decisão de seleção.
- Execute os testes do servidor, que fazem uma requisição HTTP ao servidor local de teste e conferem a resposta. Não substitua essa prova por uma resposta fabricada.
- Inicie a aplicação com npm start dentro de pratica. Abra http://127.0.0.1:3000 e confira o catálogo, o estado vazio e o estado de erro conforme os roteiros.
- Interrompa a execução ao terminar e registre o que foi observado. Uma inspeção manual pendente deve permanecer pendente, mesmo quando todos os testes automáticos passaram.
Prova real de uma fronteira
Este módulo de teste completo usa criarServidor e um arquivo temporário de dados sintéticos. É um exemplo adicional para tests/servidor.test.mjs; ao integrá-lo, reúna imports existentes uma vez. O servidor escolhe uma porta livre porque listen recebe zero. await aguarda a escuta e a resposta; finally fecha recursos mesmo quando uma asserção falha.
import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtemp, writeFile, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { once } from 'node:events';
import { criarServidor } from '../src/servidor.mjs';
test('integra arquivo, catálogo e resposta HTTP', async () => {
const pasta = await mkdtemp(join(tmpdir(), 'caracol-livro-'));
const arquivoDados = join(pasta, 'casos.json');
const servidor = criarServidor({ arquivoDados });
try {
await writeFile(arquivoDados, JSON.stringify([
{ id: 'a', titulo: 'Ativo', descricao: 'Exemplo A', ativo: true },
{ id: 'b', titulo: 'Interno', descricao: 'Exemplo B', ativo: false }
]));
servidor.listen(0, '127.0.0.1');
await once(servidor, 'listening');
const base = `http://127.0.0.1:${servidor.address().port}`;
const resposta = await fetch(`${base}/api/casos`);
assert.equal(resposta.status, 200);
assert.deepEqual(await resposta.json(), [
{ id: 'a', titulo: 'Ativo', descricao: 'Exemplo A' }
]);
} finally {
if (servidor.listening) {
await new Promise((resolve, reject) => {
servidor.close(erro => erro ? reject(erro) : resolve());
});
}
await rm(pasta, { recursive: true, force: true });
}
});O resultado esperado é HTTP 200 e um único objeto público, sem o caso b e sem a propriedade ativo. O teste exercita arquivo, seleção e serialização reais. Não abre uma página nem executa o JavaScript do navegador; essa limitação impede chamá-lo de prova completa da interface.
Comparar três evidências
| Evidência | O que demonstra | O que ainda falta |
|---|---|---|
| Teste da função com lista em memória | A decisão local seleciona apenas ativos nesse caso. | Leitura do arquivo, serialização HTTP e comportamento no navegador. |
| Teste do servidor com dados sintéticos | O caminho HTTP exercitado respeita o contrato esperado. | Renderização e interação com teclado na interface real. |
| Roteiro manual no navegador | Os passos efetivamente executados produziram o resultado registrado. | Cobertura de outros navegadores, tecnologias assistivas e cenários não executados. |
Um mock é um substituto controlado de uma dependência. Ele ajuda a produzir uma falha rara de maneira repetível. Se o teste substitui o servidor inteiro por uma função que sempre devolve sucesso, ele não verifica a integração HTTP real. Também não deve ser descartado: ele responde a outra pergunta. Declare exatamente onde começa e termina cada prova.
Um registro de integração que cabe ser auditado
Modelo preenchido de plano, ainda sem execução: unidade U-ATIVOS; requisitos REQ-001/REQ-002; arquivos afetados identificados no diff; entradas ativo e inativo; expectativa de somente ativo na resposta e na página; comandos npm test e npm run validate; roteiro de navegador e teclado a executar; limite de dados sintéticos e servidor local. Após executar, acrescente o resultado observado e a referência ao log. Antes disso, o campo resultado permanece “pendente”, e não “aprovado previsto”.
O gate integrado exige que as fronteiras obrigatórias desse escopo funcionem, que falhas impeditivas tenham sido resolvidas e que exceções não impeditivas tenham decisão explícita da autoridade definida. Atualize a rastreabilidade da unidade para não manter M6 baseado em um contrato que a alteração invalidou. Uma mudança relevante reabre a evidência afetada; o simples passar dos dias só a invalida quando houver política de validade.
Erros e reparos
- Arquivo correto, fluxo quebrado: examine o formato recebido por cada consumidor e acrescente uma prova na fronteira que falhou.
- Mock que vira dependência definitiva: conecte o contrato real antes do gate integrado e mantenha o mock apenas no teste que necessita dele.
- Mudança colateral no estilo ou nas rotas: retire-a do diff ou abra outra unidade com objetivo e autorização próprios.
Exercício com resolução
Fornecido: o teste da função passa; o teste HTTP recebe uma lista correta; no navegador aparece “Catálogo indisponível”, pois a página tenta ler resposta.itens, mas a rota documentada devolve uma lista diretamente. O autor marcou M6. Qual decisão deve ser tomada?
Ver solução comentada
Resolução: a integração não foi comprovada; M6 não é sustentado. Confirme primeiro qual contrato foi aprovado, corrija o consumidor incompatível e proteja a fronteira com teste ou roteiro específico. Depois repita o fluxo. A rubrica exige localizar a divergência, preservar o formato aprovado, diferenciar as provas já válidas da prova ausente e manter o estado pendente até nova execução. Acrescentar “mais contexto à IA” sem reparar o contrato não resolve o defeito.
Leitura técnica relacionada
S09: Fowler, Continuous Integration, especialmente a integração frequente e a construção autoverificável. S19: Node.js, HTTP server e test runner, para as fronteiras reais exercitadas no projeto.
Fontes relacionadas
Consulte os limites e as seções de apoio de cada referência.
S09 S19Tente o exercício antes de consultar a solução. Marque a aula para organizar sua leitura.
A conclusão desta leitura não equivale a certificação ou aceite de um projeto real. Teste os exemplos no escopo indicado e registre as limitações.