ConstructiCat Logo
CodeBust.
Browse section ▾

Teste Desconhecido.

Um método de teste que exercita o código mas não contém nenhuma asserção, de modo que passa desde que nada lance uma exceção — deixando desconhecido seu real propósito e o que ele verifica.

##Signs and Symptoms

Um teste que configura objetos e chama o sistema sob teste e então para sem uma única asserção. Ele está verde simplesmente porque nenhuma exceção foi lançada — não porque algum comportamento esperado foi confirmado. Nada no corpo declara como é o "correto".

Sinais reveladores:

  • Nenhum expect/assert/verify em lugar algum do corpo do teste.
  • "Verificação" feita por console.log/print do resultado que um humano supostamente deveria conferir a olho.
  • Um nome de teste vago (testChainDependencies) e um corpo que não dá nenhuma pista do que ele garante.
  • O teste continuaria verde mesmo que o método de produção retornasse um valor completamente errado.
  • Testes que se apoiam inteiramente em "não lançou exceção" sem dizê-lo explicitamente.
// Smell: roda código, imprime, não faz asserção alguma — passa não importa o que calculate() retorne
test('chain dependencies', () => {
  const game = Game.newGame(0, '');
  game.setOtherGoods(Building.TOOLMAKERS, 1);
  const logic = new Logic(game);

  const res = logic.calculateChainWithDependencies(Goods.TOOLS);
  console.log(res.toString()); // sem expect(...) — o que isso está verificando?
});

Uma variante comum se esconde atrás de mocking pesado: o teste configura mocks e chama o SUT, mas nunca faz asserção sobre um valor de retorno ou sobre as interações com os mocks.

##Reasons for the Problem

Por que acontece

  • Um teste de espaço reservado/TODO foi gerado como esqueleto ("faça compilar e rodar") e a asserção nunca foi preenchida.
  • Andaime de depuração — console.log, uma verificação manual — acabou commitado como se fosse um teste.
  • Uma refatoração excluiu ou comentou a asserção, mas deixou a configuração (setup) para trás.
  • "Roda sem lançar exceção" é confundido com "funciona." Testes de fumaça (smoke tests) são legítimos, mas aqui a intenção de fazer um smoke test nunca é tornada explícita.
  • Stubs de teste gerados automaticamente ou por IA que exercitam um método sem verificar o resultado.

Por que prejudica

  • Falsa confiança. O teste contribui para a barra verde e para a cobertura de linhas/ramos, mas não verifica nada. As métricas de cobertura mentem ativamente sobre o quão protegido o código está.
  • Nenhuma proteção contra regressões. O comportamento pode quebrar silenciosamente — valor de retorno errado, estado errado — e a suíte continua verde. Este é o pior tipo de teste: custa manutenção mas não pega nada.
  • Intenção desconhecida. Um leitor (ou futuro mantenedor) não consegue dizer qual comportamento é garantido, então não pode alterar com segurança o código ou o teste. Ele não documenta nada.
  • Corrói a confiança na suíte. Quando as pessoas percebem testes que não testam de verdade, elas param de acreditar que verde significa bom — minando todos os outros testes também.

É a imagem espelhada da Roleta de Asserções: aquele code smell tem asserções demais e sem documentação; o Teste Desconhecido não tem nenhuma.

##Treatment

Faça cada teste declarar o que ele espera e torne "apenas não deve lançar exceção" uma escolha explícita e deliberada.

  1. Adicione pelo menos uma asserção sobre um resultado observável — o valor de retorno, o estado resultante ou um erro lançado. Substitua a depuração com console.log/print por um expect sobre esse valor.
  2. Se a intenção real é "isto não deve lançar exceção," diga isso explicitamente com expect(() => fn()).not.toThrow() (ou await expect(fn()).resolves.toBeDefined()). Agora o smoke test está documentado em vez de acidental.
  3. Para testes apenas de interação, faça asserção sobre o colaborador: expect(mock).toHaveBeenCalledWith(...).
  4. Exclua ou marque com skip/todo espaços reservados mortos em vez de deixar um teste verde vazio (it.todo('handles chained deps') registra a lacuna honestamente sem fingir cobertura).
  5. Ative um detector (jest/expect-expect, vitest/expect-expect ou SonarSource S2699) na CI. Se você encapsular asserções em helpers personalizados, registre-os pela opção assertFunctionNames da regra para que asserções genuínas não sejam sinalizadas.
// Antes — Teste Desconhecido
test('chain dependencies', () => {
  const logic = new Logic(Game.newGame(0, ''));
  const res = logic.calculateChainWithDependencies(Goods.TOOLS);
  console.log(res.toString());
});

// Depois — intenção e garantia são explícitas
test('resolves tools to the toolmakers workshop chain', () => {
  const logic = new Logic(Game.newGame(0, ''));
  const res = logic.calculateChainWithDependencies(Goods.TOOLS);
  expect(res).toHaveLength(1);
  expect(res[0].building).toBe(Building.TOOLMAKERS);
});

##Detected by

  • eslint-jest expect-expectjest/expect-expect
  • eslint-vitest expect-expectvitest/expect-expect
  • sonar S2699Os testes devem incluir asserções (JavaScript)
  • sonar S2699Os testes devem incluir asserções (Java)