---
title: "Duplicação de Código de Teste"
type: "test-smell"
slug: "test-code-duplication"
url: "http://localhost:3000/pt-br/test-smells/test-code-duplication.md"
category: "Maus Cheiros Obscuros"
description: "Duplicação de Código de Teste é quando o mesmo código de configuração, ação ou asserção é copiado e colado em muitos testes, de modo que uma única mudança força edições em muitos lugares e os testes apodrecem em cópias frágeis e quase idênticas."
---
# Duplicação de Código de Teste

> Duplicação de Código de Teste é quando o mesmo código de configuração, ação ou asserção é copiado e colado em muitos testes, de modo que uma única mudança força edições em muitos lugares e os testes apodrecem em cópias frágeis e quase idênticas.

## Signs and Symptoms

Você reconhece esse smell quando os testes parecem ter sido escritos com copiar e colar em vez de reúso:

* A **mesma construção de fixture/objeto** é reconstruída literalmente no topo de teste após teste.
* **Sequências de asserção idênticas** (as mesmas 3–4 chamadas de `expect` na mesma ordem) se repetem entre os testes.
* Novos testes são obviamente clonados de um antigo com uma única linha ajustada.
* Os **mesmos literais mágicos** (IDs, URLs, datas, strings de erro) aparecem repetidamente.
* Uma mudança em um construtor ou na assinatura de uma API quebra **dezenas de testes de uma só vez** (cirurgia com espingarda).
* Você vê **testes quase duplicados que diferem apenas nos valores de entrada/esperados** — um claro candidato a um teste parametrizado/de tabela.

```js
test('flight can be cancelled', () => {
  const airport = new Airport('YYC', 'Calgary');                              // duplicado
  const flight  = new Flight('AC123', airport, new Date('2026-06-01T10:00')); // duplicado
  flight.cancel();
  expect(flight.status).toBe('CANCELLED');
});

test('flight can be delayed', () => {
  const airport = new Airport('YYC', 'Calgary');                              // copiar e colar
  const flight  = new Flight('AC123', airport, new Date('2026-06-01T10:00')); // copiar e colar
  flight.delay(30);
  expect(flight.status).toBe('DELAYED');
});

```

## Reasons for the Problem

**Por que acontece**

* Copiar e colar o teste anterior é a forma mais rápida de escrever o próximo.
* Os testes são tratados como "cidadãos de segunda classe" — não são refatorados nem mantidos no mesmo padrão DRY que o código de produção.
* Não existem fixtures compartilhadas, Creation Methods ou builders de dados de teste, e os autores não estão familiarizados com testes parametrizados/orientados a tabela.

**Por que é prejudicial**

* **Manutenibilidade:** Meszaros liga esse smell diretamente ao _Fragile Test_ — quando "as mesmas sequências de código aparecem muitas vezes em muitos testes", uma única mudança em produção significa editar a mesma coisa em N lugares. O custo de manutenção cresce com o número de cópias, não com o número de comportamentos distintos.
* **Legibilidade:** o boilerplate repetido enterra a única linha que de fato torna cada teste diferente, de modo que os leitores não conseguem ver rapidamente o que está sendo verificado.
* **Confiabilidade:** copiar e colar convida a erros de cópia, e as correções acabam aplicadas a uma cópia, mas não às suas irmãs, deixando testes inconsistentes e contraditórios.
* **Falsa confiança:** uma asserção falha que foi duplicada agora está errada em muitos lugares ao mesmo tempo, e os testes clonados se desviam silenciosamente até não exercitarem mais o que seus nomes afirmam.

**Ressalva — DRY vs DAMP:** os testes também valorizam ser _Descriptive And Meaningful Phrases_. Não abstraia demais a ponto de o leitor ter que perseguir helpers para entender um teste. Extraia a duplicação genuína, reveladora de intenção; mantenha o detalhe essencial de cada teste visível e local.

## Treatment

Elimine a duplicação _incidental_ mantendo óbvia a essência de cada teste:

1. **Extraia Test Utility / Creation Methods** (Object Mother, Test Data Builder) para a construção repetida de objetos, de modo que cada teste nomeie apenas os valores com os quais se importa.
2. **Use `beforeEach` / Implicit Setup** para o contexto que é genuinamente compartilhado e relevante para todos os testes do bloco — mas evite esconder o estado do qual um teste depende (isso troca a duplicação por um _Obscure Test_).
3. **Extraia Custom Assertions / helpers de verificação** para sequências de asserção de múltiplos passos que se repetem, idealmente verificando uma única condição lógica.
4. **Una testes quase idênticos em testes Parametrizados / orientados a tabela** (`it.each` / `test.each`), para que os pares de entrada + saída esperada fiquem em uma única tabela.
5. **Substitua os literais mágicos duplicados** por constantes nomeadas ou por valores padrão do builder.

Antes — construção duplicada e três testes quase idênticos:

```js
test('rejects negative amount', () => {
  expect(() => validateAmount(-1)).toThrow(RangeError);
});
test('rejects zero amount', () => {
  expect(() => validateAmount(0)).toThrow(RangeError);
});
test('rejects NaN amount', () => {
  expect(() => validateAmount(NaN)).toThrow(RangeError);
});

```

Depois — um Creation Method remove a duplicação da configuração, e uma tabela substitui os clones:

```js
// Creation Method compartilhado: os testes declaram apenas os overrides que importam
const aFlight = (overrides = {}) =>
  new Flight('AC123', new Airport('YYC', 'Calgary'),
             new Date('2026-06-01T10:00'), overrides);

it.each([-1, 0, NaN])('rejects invalid amount %p', (amount) => {
  expect(() => validateAmount(amount)).toThrow(RangeError);
});

```

Execute um detector de copiar e colar (abaixo) sobre os fontes dos seus testes e, então, refatore primeiro os blocos maiores/mais repetidos.

## Detected by

- **eslint-sonarjs** `no-identical-functions` — Funções não devem ter implementações idênticas (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-identical-functions.md)
- **eslint-sonarjs** `no-duplicate-string` — Literais de string não devem ser duplicados (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-duplicate-string.md)
- **sonar** `javascript:S4144` — Funções não devem ter implementações idênticas (https://rules.sonarsource.com/javascript/RSPEC-4144/)
- **pmd** `cpd` — Copy/Paste Detector (CPD) — blocos de código duplicados (https://pmd.github.io/pmd/pmd_userdocs_cpd.html)
