Teste de mesa: executar o algoritmo no papel
A técnica de rodar o algoritmo à mão numa tabela de variáveis, linha a linha, e achar o bug antes de executar, com o Node confirmando o resultado.
Teste de mesa é a execução manual de um algoritmo: você escolhe uma entrada, percorre os passos na ordem e anota o estado das variáveis depois de cada mudança. A tabela torna visível a primeira linha em que o resultado real se afasta do esperado.
O caso desta explicação é a média de quatro notas. O resultado mental é 8 para [7, 8, 9, 8]. A implementação defeituosa começa o acumulador em 1, então produz 8,25. Em vez de olhar a última linha e tentar adivinhar, vamos localizar o primeiro estado impossível.
Por que o papel ainda vence o depurador no começo
O depurador mostra com precisão o que o programa fez. O papel exige que você preveja o que ele deveria fazer. Essa diferença ensina a ler atribuição, condição e laço sem depender de botões da ferramenta. Quando previsão e execução discordam, você ganha uma pergunta concreta.
Pense num extrato bancário. O saldo final errado não diz qual lançamento causou o desvio; a sequência de saldos mostra o primeiro lançamento suspeito. Na analogia, cada linha é um estado depois de uma instrução. O limite é que programas também têm chamadas assíncronas, objetos compartilhados e estado externo; uma tabela simples não representa tudo.
O teste de mesa não substitui teste automatizado nem depurador. Ele funciona como lente inicial para uma função pequena ou um caminho específico. Depois que o raciocínio está claro, automatize os casos para impedir regressão.
Prepare quatro coisas antes de preencher
Você precisa do algoritmo numerado, da entrada concreta, do resultado esperado e das colunas de estado. Sem expectativa, qualquer saída parece possível. Sem entrada concreta, as variáveis continuam abstratas.
O pseudocódigo defeituoso é:
1. receber notas
2. soma recebe 1
3. contador recebe 0
4. enquanto contador for menor que quantidade de notas
5. soma recebe soma + nota na posição contador
6. contador recebe contador + 1
7. média recebe soma / quantidade de notas
8. devolver médiaPseudocódigo vem antes do JavaScript porque o objetivo é enxergar o estado, não discutir sintaxe. Numere operações que mudam variável ou escolhem caminho. A linha do enquanto também entra no rastreio porque seu resultado decide se haverá outra volta.
Uma coluna por variável e uma linha por passo executado
As colunas mínimas são passo, soma, contador e media. Também registramos a condição para não esconder a avaliação do laço. Um traço significa “ainda não existe”, não zero.
| passo executado | condição contador < 4 |
soma | contador | média |
|---|---|---|---|---|
| entrada | — | — | — | — |
soma = 1 |
— | 1 | — | — |
contador = 0 |
— | 1 | 0 | — |
| testar laço | true | 1 | 0 | — |
| somar nota 7 | — | 8 | 0 | — |
| incrementar | — | 8 | 1 | — |
| testar laço | true | 8 | 1 | — |
| somar nota 8 | — | 16 | 1 | — |
| incrementar | — | 16 | 2 | — |
| testar laço | true | 16 | 2 | — |
| somar nota 9 | — | 25 | 2 | — |
| incrementar | — | 25 | 3 | — |
| testar laço | true | 25 | 3 | — |
| somar nota 8 | — | 33 | 3 | — |
| incrementar | — | 33 | 4 | — |
| testar laço | false | 33 | 4 | — |
| dividir por 4 | — | 33 | 4 | 8,25 |
A tabela tem mais linhas que o pseudocódigo porque as linhas 4 a 6 executam repetidamente. Esse é um ganho, não burocracia: o papel expõe a ordem temporal que o texto compacto do laço esconde.
A primeira divergência aparece antes da primeira volta
Você sabe que nenhuma nota foi somada ainda. Portanto o elemento neutro da soma deveria ser zero. A linha soma = 1 já cria uma diferença de um ponto que atravessará todas as voltas. Não é preciso chegar à divisão para localizar a causa.
Esse diagnóstico é melhor que trocar o divisor até “dar 8”. Alterar o divisor trataria o sintoma para uma lista específica e criaria outro erro em todas as demais. Teste de mesa orienta uma correção mínima: iniciar o acumulador em zero.
O princípio vale para outros estados. Produto começa em um porque um é o elemento neutro da multiplicação. Contador começa em zero quando ainda não houve ocorrências. Maior valor não deve começar sempre em zero se a lista pode conter somente negativos; ele pode começar no primeiro elemento.
O Node confirma o papel, inclusive no erro
A versão defeituosa reproduz exatamente os estados principais:
function mediaComErro(notas) {
let soma = 1;
let contador = 0;
while (contador < notas.length) {
soma += notas[contador];
contador += 1;
}
return soma / notas.length;
}
console.log(mediaComErro([7, 8, 9, 8]));O valor não é uma exceção do runtime; é um erro lógico. O Node executou corretamente um algoritmo que descrevemos errado. Essa distinção importa: stack trace ajuda em exceções, mas não aparece quando o programa calcula uma resposta plausível.
Corrija somente o estado inicial:
function media(notas) {
let soma = 0;
let contador = 0;
while (contador < notas.length) {
soma += notas[contador];
contador += 1;
}
return soma / notas.length;
}
console.log(media([7, 8, 9, 8]));Agora a primeira linha de estado é compatível com “nenhuma nota somada”. A lição de acumulador e média aprofunda elementos neutros e lista vazia.
O desenho liga fluxo e tabela
Fluxograma responde “qual passo vem depois?”; tabela de mesa responde “qual valor existe quando ele vem?”. Os dois modelos se complementam:
As setas dizem que o teste acontece novamente depois do incremento. As colunas mostram que, nessa volta, soma e contador já carregam novos valores. Leia fluxograma e pseudocódigo para treinar a primeira metade desse par.
Dentro de um laço, rastreie as voltas que explicam o defeito
Uma lista de dez mil itens não pede dez mil linhas de papel. Escolha o começo, o ponto de divergência e a borda final. Para erro de um a mais, as duas últimas avaliações são mais informativas que o meio do laço.
for (let i = 0; i <= 3; i += 1) {
console.log({ i, condicao: i <= 3 });
}
console.log({ i: 4, condicao: 4 <= 3, executaCorpo: false });O estado i=4 existe na avaliação, mas não entra no corpo. Essa separação corrige a frase imprecisa “o laço terminou no três”: o último corpo usou três; a condição que encerrou usou quatro. A lição de laço e contador mostra a contagem completa.
Escolha entradas que forçam caminhos diferentes
Um caso normal prova somente o caminho normal. Para média, use pelo menos: quatro notas conhecidas, uma única nota, lista vazia e valores decimais. Para condição, use abaixo, igual e acima do limite. Para busca, use resposta no primeiro item, no último e ausente.
A lista vazia revela outro defeito da função corrigida:
function media(notas) {
const soma = notas.reduce((total, nota) => total + nota, 0);
return soma / notas.length;
}
console.log(media([]));
console.log(Number.isNaN(media([])));JavaScript não lança erro ao dividir zero por zero; produz NaN. O teste de mesa teria soma=0, quantidade=0 e 0/0, chamando atenção antes da execução. A regra de produto precisa decidir: lista vazia é erro, retorna zero ou não deveria chegar à função?
Onde a técnica deixa de bastar
Concorrência, temporizadores, rede, banco e mutação compartilhada podem produzir ordens difíceis de representar numa tabela manual. Nesses casos, use logs com contexto, depurador, testes automatizados e observabilidade. Mesmo assim, ainda vale recortar uma função pura e rastrear a parte determinística.
O teste de mesa também não garante cobertura sozinho. Você pode preencher a tabela perfeitamente para uma entrada incapaz de visitar o ramo defeituoso. A escolha dos casos é parte da técnica, não uma etapa posterior.
Compare invariantes, não somente números finais
Invariante é uma afirmação que deve continuar verdadeira durante certo trecho. Na média, contador nunca pode ultrapassar a quantidade de notas processadas, e soma precisa representar exatamente os itens anteriores ao índice atual. Registrar a afirmação ao lado da tabela ajuda a detectar um estado impossível antes de conhecer a saída final.
Em busca, uma invariante pode dizer que o alvo não apareceu nas posições já visitadas. Em ordenação por seleção, o prefixo antes da posição atual já está ordenado e contém os menores valores. A técnica muda de simples cópia de variáveis para revisão do motivo pelo qual cada passo é válido.
Use unidades nas colunas. tempoSegundos e distanciaMetros impedem uma divisão tecnicamente executável e conceitualmente errada. Quando um valor muda de unidade, crie nova coluna em vez de sobrescrever e perder a origem da transformação.
Transforme a tabela em casos automatizados
Cada entrada e saída final pode virar teste. Estados intermediários não precisam todos aparecer na suíte pública; eles servem para localizar a causa durante desenvolvimento. Preserve especialmente bordas e regressões: o caso que revelou o acumulador iniciado em um nunca deve desaparecer.
Nomeie o teste pelo comportamento, como “média de lista vazia rejeita entrada”, e não pela função interna. Assim a implementação pode mudar sem apagar o contrato. Quando o teste falha, refaça uma tabela curta com a entrada daquele cenário, compare a primeira divergência e corrija somente a causa.
O papel continua útil mesmo depois de adotar ferramenta. Você pode desenhar uma hipótese em dois minutos antes de encher o código de logs. A disciplina é formular o estado esperado; a mídia — papel, planilha ou depurador — é secundária.
Uma revisão em dupla melhora a hipótese
Peça para a outra pessoa escolher a entrada e preencher uma coluna, enquanto você executa os passos. Divergências de interpretação revelam pseudocódigo ambíguo. Depois troquem os papéis e usem um caso de borda.
Não diga o bug antes da simulação. Se a pessoa encontra a linha do acumulador sem pista, a tabela está cumprindo o papel de diagnóstico. Se ela só percebe depois de receber a resposta, acrescente expectativa e invariante mais cedo no processo.
Arquive apenas tabelas que explicam uma regra ou um defeito importante. O objetivo não é produzir papel para toda execução, mas preservar o raciocínio que será útil quando o requisito voltar a mudar. Uma tabela pequena com entrada, primeira divergência e correção ensina mais que dezenas de estados sem hipótese.
Sua missão é rastrear no papel um desconto por faixas para valores 99, 100 e 101. Numere passos, anote condição e resultado, e marque a primeira linha que muda entre os casos. Depois transforme cada linha final em um teste executável. Use a estrutura condicional para a regra, o guia de lógica para situar a técnica e a trilha de Lógica para continuar.
Perguntas frequentes
Teste de mesa é a mesma coisa que depurar com breakpoint?
Preciso rastrear todas as linhas de um programa grande?
Qual entrada usar primeiro no teste de mesa?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Node v26.3.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- Node.js — Debugging Getting Started — nodejs.org
- ECMAScript — Execution Contexts — tc39.es


