---
title: "Número Mágico em Teste"
type: "test-smell"
slug: "magic-number-test"
url: "http://localhost:3000/pt-br/test-smells/magic-number-test.md"
category: "Maus Cheiros Obscuros"
description: "Um teste fixa literais numéricos sem explicação em suas entradas e asserções, escondendo o que os números significam e de onde vieram."
---
# Número Mágico em Teste

> Um teste fixa literais numéricos sem explicação em suas entradas e asserções, escondendo o que os números significam e de onde vieram.

## Signs and Symptoms

Você identifica um Número Mágico em Teste quando os argumentos e as asserções de um teste estão repletos de números soltos cujo significado e origem não são óbvios a partir do código. O leitor precisa fazer engenharia reversa (ou simplesmente confiar) sobre por que um valor específico é esperado.

Sinais reveladores:

* Literais numéricos aparecem diretamente como argumentos de asserção: `expect(result).toBe(54.13)`, `assertEquals(86400, ttl)`.
* O mesmo literal se repete na configuração, na ação e no valor esperado, sem nenhum nome que os una.
* Os números codificam conceitos de domínio que não são explicitados (`3600` \= uma hora, `200` \= HTTP OK, `0.0825` \= uma alíquota de imposto).
* Um comentário no código fica ao lado do número para explicá-lo — um sinal de que o próprio número deveria ter sido nomeado.
* Durante a revisão, as pessoas perguntam "por que `42`?" ou "de onde vem `54.13`?" e ninguém consegue responder sem reexecutar o código.

```js
// Smell: o que é 8.25? por que 54.13? o que é o 50 escondido dentro do helper?
test('checkout works', () => {
  const total = checkout(cartFor(50), 8.25);
  expect(total).toBe(54.13);
});

```

Esta é uma variante específica, do lado dos testes, do smell geral _Número Mágico_, e um clássico contribuinte para o smell **Obscure Test** (Meszaros): o leitor não consegue entender o teste apenas a partir do teste.

## Reasons for the Problem

**Por que acontece**

* O literal é o caminho de menor resistência: você digita o valor que viu em um depurador ou copia a saída real de uma execução que falhou para dentro da asserção até que ela fique verde ("adivinhe o valor" / colar a saída).
* O autor já tem o contexto de domínio na cabeça, então `3600` ou `8.25` parece autoevidente _no momento da escrita_.
* Os valores da fixture são escolhidos arbitrariamente (`new User(25, ...)`) apenas para satisfazer o construtor, sem pensar no significado.

**Por que é prejudicial**

* **Legibilidade / intenção.** Um número como `54.13` declara um fato, mas não uma razão. Revisores e futuros mantenedores não conseguem dizer se é uma expectativa deliberada, um limite ou um acidente. O teste deixa de ser documentação executável.
* **Manutenibilidade.** Quando a regra muda (a alíquota de imposto, o timeout, o tamanho da página), você precisa caçar cada cópia do literal e saber qual `7` significava "dias" e qual significava "máximo de tentativas". A duplicação sem nome torna as edições seguras caras e propensas a erros.
* **Confiabilidade / falsa confiança.** Se o valor esperado está errado — ou certo apenas por coincidência — nada no teste revela isso. Pior, os autores muitas vezes "corrigem" um teste com número mágico recalculando o valor esperado com a fórmula de _produção_ (`expect(total).toBe(subtotal * (1 + rate)))`), transformando a asserção em uma tautologia que reimplementa o código sob teste e nunca pode falhar pela razão certa.
* **Diagnóstico.** Quando um teste desses quebra, a mensagem de falha é apenas "esperado 54.13, obtido 54.12", sem nenhuma pista sobre qual entrada ou regra produziu o número, o que torna a depuração mais lenta.

## Treatment

Aplique **Replace Magic Number with Symbolic Constant** (Meszaros): dê a cada valor significativo um nome que explique seu papel e torne explícita a relação entre as entradas e o resultado esperado.

Passos concretos:

1. **Nomeie as entradas.** Extraia os literais usados como dados de teste para constantes locais bem nomeadas ou chamadas de fixture-builder (`const SUBTOTAL = 50.00`, `const TAX_RATE_PCT = 8.25`). Use um Object Mother / builder para fixtures de objeto, de modo que apenas os valores que importam para o teste fiquem visíveis.
2. **Nomeie e explique o valor esperado.** Mantenha o resultado esperado como um literal _independente_, mas dê-lhe um nome e documente como ele foi derivado (`const EXPECTED_TOTAL = 54.13; // 50.00 + 8.25% de imposto`). **Não** o recalcule com a fórmula de produção — isso apenas testa o código contra ele mesmo.
3. **Vincule as entradas à asserção** para que o leitor possa verificar a aritmética a olho nu, ou faça a asserção contra um valor de referência derivado, porém independente.
4. **Deixe em paz os valores genuinamente autoevidentes.** `0`, `1`, `-1`, índices de array e contagens óbvias (`items).toHaveLength(2)`) normalmente não precisam de nomes; reserve as constantes para valores cujo significado não é autoexplicativo. Promova uma constante compartilhada a uma única fonte de verdade somente quando ela for realmente o mesmo conceito em todos os lugares.

```js
// Antes
test('checkout works', () => {
  const total = checkout(cartFor(50), 8.25);
  expect(total).toBe(54.13);
});

// Depois
const SUBTOTAL = 50.00;
const TAX_RATE_PCT = 8.25;
const EXPECTED_TOTAL = 54.13; // SUBTOTAL mais 8.25% de imposto sobre vendas

test('applies sales tax to the subtotal', () => {
  const total = checkout(cartFor(SUBTOTAL), TAX_RATE_PCT);
  expect(total).toBe(EXPECTED_TOTAL);
});

```

Agora os nomes carregam a intenção; se a regra de imposto mudar, a edição é local e óbvia, e o valor esperado continua sendo uma verificação honesta e independente, em vez de uma tautologia.

## Detected by

- **eslint** `no-magic-numbers` — Números mágicos devem ser declarados como constantes nomeadas (https://eslint.org/docs/latest/rules/no-magic-numbers)
- **typescript-eslint** `@typescript-eslint/no-magic-numbers` — Proibir números mágicos (TypeScript) (https://typescript-eslint.io/rules/no-magic-numbers/)
- **sonar** `javascript:S109` — Números mágicos não devem ser usados (https://rules.sonarsource.com/javascript/RSPEC-109/)
- **checkstyle** `MagicNumber` — MagicNumber (https://checkstyle.sourceforge.io/checks/coding/magicnumber.html)
- **tsDetect** `Magic Number Test` — Magic Number Test (detector específico para testes) (https://testsmells.org/pages/testsmells.html)
