SkillsTecnológicas
Menu
Conteúdo da trilha

Teste de mesa e rastreamento de variáveis

Aprenda a projetar tabelas de teste de mesa, registrar mudanças de estado e rastrear decisões, laços, funções e resultados sem pular etapas.

Conteúdo 47 de 52

Grade desenhada a lápis acompanha peças de madeira que mudam entre estados, atravessam uma decisão e chegam a uma verificação

Uma tabela de rastreamento transforma execução em estado observável

Um teste de mesa simula um algoritmo com uma entrada concreta. O rastreamento de variáveis é o registro disciplinado dessa simulação: em momentos definidos, você anota quais instruções foram executadas, quais condições foram avaliadas e qual valor cada variável possui.

O objetivo não é copiar o algoritmo inteiro para uma tabela. É produzir uma sequência de estados que responda três perguntas:

  1. onde a execução está?
  2. qual decisão acabou de ser tomada?
  3. o que mudou em relação ao estado anterior?

Se o resultado estiver errado, a tabela permite procurar a primeira linha em que o estado obtido deixa de corresponder ao esperado. Ela aprofunda o procedimento apresentado em como testar um algoritmo manualmente e torna o diagnóstico reproduzível.

Defina o ponto de captura antes de preencher a tabela

Uma variável pode ter valores diferentes antes e depois da mesma instrução. Por isso, toda tabela precisa declarar quando cada linha é registrada.

Considere:

total = total + valor

Se total vale 7 e valor vale 4, o estado anterior à instrução contém total = 7; o estado posterior contém total = 11. Os dois registros são corretos, mas não podem ser misturados na mesma convenção.

Para laços, uma escolha prática é criar:

  • uma linha de inicialização;
  • uma linha após cada execução completa do corpo;
  • uma linha final para a condição de saída ou para o resultado.

Quando o objetivo é investigar uma condição, registre também o estado imediatamente antes da decisão. Escreva a convenção acima da tabela: “valores após o corpo”, “valores antes da condição” ou outra descrição inequívoca.

Uma instrução separa duas fotografias do estado, mostrando total sete antes e total onze depois da atualização com valor quatro
O ponto de captura define se uma célula descreve o estado que entrou na instrução ou o estado produzido por ela.

Escolha colunas que expliquem o comportamento

Comece pela pergunta que o rastro precisa responder. Depois escolha as colunas.

Uma tabela costuma combinar quatro tipos de informação:

TipoO que registrarExemplo
localizaçãoetapa, iteração ou linha lógicaiteração 2
entrada correntevalor que está sendo processadonota = 9
controlecondição e caminho selecionadonota >= 5 → verdadeiro
estado acumuladovalores que sobrevivem entre passossoma = 16, quantidade = 2

Não inclua todas as variáveis por hábito. Uma constante que nunca muda pode aparecer no cabeçalho ou numa observação. Uma variável temporária irrelevante para a pergunta pode ficar de fora. Em contrapartida, não omita uma condição que decide se o estado será atualizado.

Use para “ainda não existe” ou “não se aplica”. Não use 0 no lugar de ausência: zero é um valor real e pode alterar a interpretação.

Construa o rastro a partir de um caso pequeno

Vamos calcular a média somente das notas maiores ou iguais a 5:

notas = [7, 4, 9, 2]
soma = 0
quantidade = 0

para indice de 0 até tamanho(notas) - 1
  nota = notas[indice]

  se nota >= 5
    soma = soma + nota
    quantidade = quantidade + 1

se quantidade > 0
  media = soma / quantidade
senão
  media = ausente

Antes de simular, calcule o esperado por um caminho independente. As notas selecionadas são 7 e 9; portanto, a soma deve ser 16, a quantidade deve ser 2 e a média deve ser 8.

O caso é pequeno, mas contém coleção, índice, variável corrente, decisão, acumulador, contador e uma proteção contra divisão por zero.

Preencha primeiro o estado inicial

Nossa convenção será: uma linha após a inicialização e uma linha após cada execução completa do corpo do laço.

Antes da primeira iteração:

MomentoÍndiceNotanota >= 5SomaQuantidade
inicialização00

indice e nota ainda não receberam valores do laço. Por isso aparecem como ausência, não como zero. Já soma e quantidade foram inicializadas explicitamente com zero.

Registrar esse estado evita atribuir ao primeiro item valores que existiam antes de ele ser lido.

Atualize uma linha de cada vez

Na primeira iteração, indice = 0 e nota = 7. A condição é verdadeira, então os dois estados acumulados mudam:

MomentoÍndiceNotanota >= 5SomaQuantidade
inicialização00
após iteração 007verdadeiro71

Na segunda, nota = 4. A condição é falsa. O algoritmo visita o item, mas não executa as duas atribuições internas. Copie os valores mantidos:

MomentoÍndiceNotanota >= 5SomaQuantidade
após iteração 114falso71

“Não mudou” também é informação. Deixar a célula vazia poderia significar ausência, esquecimento ou permanência. Repetir 7 e 1 torna o estado completo.

Complete as duas iterações restantes:

MomentoÍndiceNotanota >= 5SomaQuantidade
inicialização00
após iteração 007verdadeiro71
após iteração 114falso71
após iteração 229verdadeiro162
após iteração 332falso162
Quatro estados mostram as notas sete, quatro, nove e dois; soma e quantidade avançam somente nas iterações aprovadas pela condição
As linhas falsas ainda fazem parte da execução, mas preservam soma e quantidade.

Registre o resultado fora do laço

Depois do percurso, quantidade > 0 é verdadeira. A última divisão produz:

media = 16 / 2
media = 8

Você pode adicionar uma linha final:

MomentoSomaQuantidadequantidade > 0Média
após o laço162verdadeiro8

Separar essa linha é importante: a média não é recalculada em cada iteração. Colocá-la nas linhas do laço sugeriria uma ordem de execução que o algoritmo não possui.

Agora compare três resultados independentes:

  • previsão anterior à simulação: 8;
  • estado final rastreado: 8;
  • saída produzida pelo algoritmo implementado: deve ser 8.

A concordância deste caso não prova que o algoritmo funciona para todas as entradas. Ela confirma somente o percurso rastreado.

Use a primeira divergência para encontrar uma atualização mal posicionada

Suponha que quantidade = quantidade + 1 tenha sido recuada por engano e fique fora do bloco condicional:

para cada nota
  se nota >= 5
    soma = soma + nota

  quantidade = quantidade + 1

O rastro observado passa a ser:

IteraçãoNotaCondiçãoSoma esperada/observadaQuantidade esperadaQuantidade observada
07verdadeiro7 / 711
14falso7 / 712
29verdadeiro16 / 1623
32falso16 / 1624

O sintoma final é média 4, mas a primeira divergência acontece na iteração 1, quando uma nota rejeitada aumenta a quantidade. A tabela liga a falha à posição da atualização.

Esse é o uso diagnóstico: não examine apenas a última linha. Compare esperado e observado de cima para baixo e pare na primeira diferença, como detalhado em como identificar erros em um algoritmo.

Em um while, mostre a condição final falsa

Um for frequentemente deixa inicialização, teste e avanço implícitos. No while, essas etapas merecem colunas próprias:

indice = 0
total = 0

enquanto indice < 3
  total = total + indice
  indice = indice + 1

Use uma linha por avaliação da condição:

AvaliaçãoÍndice antes do corpoindice < 3Total após o corpoÍndice após o corpo
10verdadeiro01
21verdadeiro12
32verdadeiro33
43falso

A última linha explica por que o laço terminou. O corpo não executou nessa avaliação, então os campos “após o corpo” não se aplicam. Essa convenção ajuda a diagnosticar condições de parada e laços infinitos.

Em laços aninhados, uma linha representa o corpo mais interno

Se uma matriz é percorrida por linha e coluna, registre as duas coordenadas. Uma linha da tabela deve corresponder a uma visita à célula, isto é, a uma execução do corpo mais interno:

para linha de 0 até 1
  para coluna de 0 até 2
    visite matriz[linha][coluna]
VisitaLinhaColunaPosição
100[0][0]
201[0][1]
302[0][2]
410[1][0]
511[1][1]
612[1][2]

A coluna interna volta ao estado inicial quando o laço externo avança. Se a tabela omitir linha, duas visitas com coluna = 0 parecerão iguais. Veja a ordem completa em estruturas de repetição aninhadas.

Em funções, separe uma chamada da outra

Variáveis locais com o mesmo nome podem pertencer a chamadas diferentes. Acrescente uma coluna de chamada ou quadro de execução:

dobrar(3) retorna 6
dobrar(5) retorna 10
ChamadaArgumentoParâmetro localRetorno
1336
25510

Não continue a segunda chamada na mesma linha da primeira como se o parâmetro local tivesse apenas mudado de 3 para 5. A primeira variável local deixa de pertencer ao contexto ativo quando a função retorna; a segunda chamada cria outro contexto. A aula sobre escopo de variáveis explica essa fronteira.

Em recursão, use uma linha por chamada e inclua profundidade, argumento recebido, estado antes da chamada interna e valor devolvido. A ordem de retorno é inversa à ordem de entrada.

Um diagrama separa rastreamento por linha e coluna de uma matriz e rastreamento por identificador de chamada de função
Coordenadas identificam visitas em laços aninhados; identificadores de chamada impedem misturar variáveis locais de execuções diferentes.

A tabela manual e o depurador observam o mesmo tipo de evidência

Um depurador executa o programa de verdade e permite avançar por instruções, pausar em breakpoints e inspecionar variáveis locais ou expressões escolhidas. Uma tabela manual prevê e registra o estado sem depender da ferramenta.

As duas abordagens podem ser comparadas:

Tabela manualDepurador
linha da tabelapausa após um passo
coluna de variávelpainel de variáveis ou watch
coluna de condiçãoexpressão avaliada
chamada identificadaquadro na pilha de chamadas

Observe o momento da pausa. Em muitos depuradores, a instrução destacada é a próxima a executar. Se a execução está parada em soma = soma + nota, a soma exibida ainda pode ser a anterior à atribuição.

Evite editar valores durante uma observação inicial. Alterar uma variável no depurador muda o experimento e pode fazer a execução seguir por um caminho que o programa normal nunca seguiria.

Erros que tornam o rastro ambíguo

Misturar valores de antes e depois

Declare o ponto de captura e mantenha-o. Se precisar observar uma instrução específica, crie colunas “antes” e “depois” ou uma tabela auxiliar.

Criar uma linha somente quando algo muda

Uma decisão falsa também é execução. Omiti-la esconde caminhos e faz parecer que itens não foram visitados.

Deixar células vazias sem convenção

Use para ausência ou não aplicável e repita valores que permaneceram iguais.

Registrar o resultado sem a condição

Se uma variável muda apenas em um ramo, a coluna da condição explica por que ela mudou ou permaneceu.

Misturar estados de chamadas ou iterações

Inclua índice, coordenadas, profundidade ou identificador de chamada suficiente para distinguir cada contexto.

Produzir uma tabela maior que a pergunta

Rastreie o menor caso que exercita o comportamento investigado. Para coleções extensas, reduza a entrada sem eliminar o caminho relevante.

Pratique com estoque acumulado

Considere este algoritmo:

movimentos = [5, -2, 4, -8]
estoque = 3
menor_estoque = estoque

para cada movimento
  estoque = estoque + movimento

  se estoque < menor_estoque
    menor_estoque = estoque

Produza uma tabela que contenha:

  1. estado inicial;
  2. índice e movimento atual;
  3. estoque antes e depois da atualização;
  4. resultado de estoque < menor_estoque;
  5. menor estoque ao final de cada iteração;
  6. resultado final esperado.

Depois mova, propositalmente, a comparação para antes da atualização de estoque. Execute o mesmo rastro e identifique a primeira linha em que menor_estoque diverge.

Seu registro está verificável se outra pessoa consegue reconstruir a ordem das instruções sem executar o código.

O que você deve guardar

Uma boa tabela de rastreamento possui um ponto de captura explícito, uma linha para cada evento relevante e somente as colunas necessárias para explicar o comportamento. Ausência, permanência e mudança precisam ser distinguíveis.

Comece pelo estado inicial, avance na ordem real, registre condições falsas e separe contextos de laços e funções. Compare o estado esperado com o observado de cima para baixo: a primeira divergência costuma ser mais útil do que o resultado final incorreto.

O próximo passo é aprender como criar casos de teste que exercitem comportamentos diferentes sem repetir entradas sem propósito.

Referências