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/verifyem lugar algum do corpo do teste. - "Verificação" feita por
console.log/printdo 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.
- 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 umexpectsobre esse valor. - Se a intenção real é "isto não deve lançar exceção," diga isso explicitamente com
expect(() => fn()).not.toThrow()(ouawait expect(fn()).resolves.toBeDefined()). Agora o smoke test está documentado em vez de acidental. - Para testes apenas de interação, faça asserção sobre o colaborador:
expect(mock).toHaveBeenCalledWith(...). - Exclua ou marque com
skip/todoespaços reservados mortos em vez de deixar um teste verde vazio (it.todo('handles chained deps')registra a lacuna honestamente sem fingir cobertura). - Ative um detector (
jest/expect-expect,vitest/expect-expectou SonarSource S2699) na CI. Se você encapsular asserções em helpers personalizados, registre-os pela opçãoassertFunctionNamesda 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-expect — jest/expect-expect
- eslint-vitest expect-expect — vitest/expect-expect
- sonar S2699 — Os testes devem incluir asserções (JavaScript)
- sonar S2699 — Os testes devem incluir asserções (Java)