AULA 30 / 61 · ACESSO GRATUITO

Da especificação para o código

Graciliano TolentinoEngenharia Caracol · Edição 2.0
Nesta aula
  1. A frase precisa de uma consequência observável
  2. Contrato preenchido de uma unidade
  3. Procedimento para construir a primeira prova
  4. Um exemplo de regra e asserção
  5. Erros que mudam o sentido do requisito
  6. Exercício com resolução
  7. Leitura técnica relacionada

A frase precisa de uma consequência observável

Um requisito descreve uma necessidade. Um contrato descreve o comportamento que uma unidade de software deve cumprir: quais entradas recebe, quais saídas produz e o que acontece quando a entrada não é aceitável. O código implementa esse acordo; o teste executa um caso e compara o resultado com uma expectativa definida antes da solução. A passagem entre esses elementos exige decisões explícitas, não uma tradução automática de português para JavaScript.

Na Oficina Caracol, REQ-002 diz que o catálogo público não revela registros inativos. A consequência alcança o servidor: esconder um cartão na página seria insuficiente se a resposta de rede ainda contivesse o registro. A lista pública precisa ser filtrada antes de atravessar essa fronteira. Os dados usados nos exercícios são fictícios. A implementação didática não precisa de cadastro, banco externo ou biblioteca adicional.

Contrato preenchido de uma unidade

CampoDecisão da Oficina
NecessidadeREQ-001 lista serviços ativos; REQ-002 exclui inativos.
EntradaLista de casos válida conforme a validação do projeto.
RegraSomente registros cujo campo ativo é o booleano true.
SaídaNova lista com os casos ativos; lista vazia é um resultado válido.
Entrada inválidaRejeição explícita na validação; não converter erro de dado em catálogo vazio.
PreservaçãoNão alterar a lista recebida; não acrescentar dependências.
Prova mínimaCaso ativo, inativo, vazio e inválido; depois verificar a rota pública.

Booleano é um tipo com dois valores, true e false. A string "false" contém texto e não significa o booleano false. Por isso, o contrato de dados precisa impedir ambiguidades. A função de seleção trabalha depois da validação do conjunto; não cabe inventar silenciosamente um significado para registros malformados.

Procedimento para construir a primeira prova

  • Escolha um requisito e escreva ao menos um exemplo que deve passar e um que deve ser recusado.
  • Localize a função e os testes existentes antes de modificar arquivos. Preserve os contratos já utilizados por outros módulos.
  • Escreva a expectativa do teste antes da implementação. A falha inicial precisa apontar o comportamento ausente, não um import com nome errado.
  • Implemente a menor alteração que atende ao contrato. Execute npm test e npm run validate dentro de pratica.
  • Compare o diff com o escopo e realize a integração com a rota e a página. Registre versão, ambiente, comando, resultado e limite.

Um exemplo de regra e asserção

O código abaixo é o recorte real da seleção em src/catalogo.mjs. validarCasos rejeita tipos, campos e identificadores inválidos; camposPublicos cria um objeto com somente os três campos que podem sair do servidor. O conjunto validado contém booleanos, por isso a condição caso.ativo seleciona precisamente os true.

javascript
function camposPublicos({id, titulo, descricao}) {
  return {id, titulo, descricao};
}

export function listarAtivos(casos) {
  validarCasos(casos);
  return casos.filter(caso => caso.ativo).map(camposPublicos);
}

filter devolve uma nova lista com os elementos que satisfazem a condição. map transforma cada selecionado no formato público. A desestruturação de camposPublicos dá nomes aos campos recebidos, e o novo objeto exclui ativo. Não copiar campos extras reduz o risco de publicar informação que não pertence ao contrato. O teste seguinte usa os exports reais e o mesmo caminho de importação de tests/catalogo.test.mjs.

javascript
import test from 'node:test';
import assert from 'node:assert/strict';
import { listarAtivos, validarCasos } from '../src/catalogo.mjs';

test('seleção cumpre o contrato público', () => {
  const entrada = [
    { id: 'revisao', titulo: 'Revisão', descricao: 'Exemplo A', ativo: true },
    { id: 'rascunho', titulo: 'Rascunho', descricao: 'Exemplo B', ativo: false }
  ];
  const antes = structuredClone(entrada);
  assert.deepEqual(listarAtivos(entrada), [
    { id: 'revisao', titulo: 'Revisão', descricao: 'Exemplo A' }
  ]);
  assert.deepEqual(entrada, antes);
  assert.deepEqual(listarAtivos([]), []);
  assert.throws(
    () => validarCasos([{ ...entrada[0], ativo: 'true' }]),
    TypeError
  );
});

deepEqual compara a estrutura esperada; structuredClone guarda uma cópia para verificar preservação da entrada. throws exige uma rejeição do tipo declarado. Essas asserções cobrem seleção, projeção, vazio, preservação e um caso inválido. Ainda não provam leitura de arquivo, resposta HTTP ou comportamento no navegador. Reúna os imports uma vez se incorporar o teste ao módulo existente; não substitua a suíte completa por esse recorte.

Erros que mudam o sentido do requisito

ErroReparo específico
Filtrar somente na interfaceVerificar a resposta pública e retirar inativos antes de enviá-la.
Aceitar "true" como se fosse trueValidar tipos e mostrar o diagnóstico de dado inválido.
Retornar [] para qualquer exceçãoDistinguir conjunto legitimamente vazio de falha de leitura ou validação.
Afirmar integração após teste de funçãoExecutar também o caminho servido pela aplicação.

O avanço desta unidade exige verificações aplicáveis aprovadas, preservações confirmadas e ausência de lacuna impeditiva. Isso sustenta M5 para o conjunto explicitamente testado. M6 requer evidência do fluxo integrado; a asserção isolada não autoriza esse estado.

Exercício com resolução

Entrada fornecida: A possui ativo true; B possui ativo false; C possui ativo true. Escreva os identificadores esperados, depois altere B para a string "true". O conjunto continua válido? Qual resultado deve ser mostrado ao usuário se a validação rejeitar o arquivo?

Ver solução comentada

Resolução: a primeira lista pública contém A e C, nessa ordem. A string torna o segundo conjunto inválido segundo o contrato booleano; não se deve publicar B nem chamar a falha de catálogo vazio. A interface deve mostrar o estado explícito de indisponibilidade previsto pelo projeto, preservando a navegação. A rubrica exige separar seleção e validação, indicar o ponto da rejeição e incluir uma asserção sobre inativos. Uma resposta que apenas imprime A e C cobre somente o primeiro caso.

Leitura técnica relacionada

S18: MDN, Array.prototype.filter, seções Syntax e Description, para a seleção e a criação de uma nova lista. S19: Node.js, módulo node:test e asserções, para executar expectativas. A ligação entre requisito, contrato e evidência apresentada aqui é a organização didática do método.

Fontes relacionadas

Consulte os limites e as seções de apoio de cada referência.

S18 S19
Conseguiu explicar o que aprendeu?

Tente 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.