---
title: "Assertion Roulette"
type: "test-smell"
slug: "assertion-roulette"
url: "http://localhost:3000/pt-br/test-smells/assertion-roulette.md"
category: "Maus Cheiros de Asserção"
description: "Um teste empacota muitas asserções não documentadas em um único método, então, quando ele falha, você não consegue saber qual asserção disparou nem por quê — é preciso apostar."
---
# Assertion Roulette

> Um teste empacota muitas asserções não documentadas em um único método, então, quando ele falha, você não consegue saber qual asserção disparou nem por quê — é preciso apostar.

## Signs and Symptoms

Um único teste contém uma sequência de asserções nuas, sem mensagens explicativas e sem um objetivo único claro. Quando ele fica vermelho, o relatório de falha (especialmente uma linha de resumo de CI ou um helper de asserção compartilhado) diz _que_ algo quebrou, mas não _qual_ verificação nem _por quê_ — você joga na "roleta" para achar o culpado.

Sinais reveladores:

* Muitas chamadas `expect(...)` / `assert(...)` em um único teste, nenhuma carregando uma mensagem ou rótulo descritivo.
* O nome do teste é genérico (`'works'`, `'user profile'`, `'test register'`), então uma falha não comunica nada por si só.
* As asserções abrangem várias preocupações não relacionadas (um [Eager Test](https://en.wikipedia.org/wiki/Test%5Fsmell) reutilizando uma única fixture para verificar tudo de uma vez).
* Uma falha faz você recorrer ao depurador ou aos números de linha para descobrir o que estava de fato sendo verificado.
* Como a maioria das asserções é fail-fast, a primeira falha interrompe o restante, então você nunca vê as verificações posteriores em uma única execução.

```js
test('user profile', () => {
  const user = createUser({ name: 'Ada', age: 36 });
  expect(user.name).toBe('Ada');
  expect(user.age).toBe(36);
  expect(user.isAdult).toBe(true);   // se ESTA for a vermelha,
  expect(user.slug).toBe('ada');     // o relatório apenas diz
  expect(user.roles).toContain('member'); // "expected false to be true"
  expect(user.createdAt).toBeInstanceOf(Date);
});

```

Observação: executores modernos (Jest, Vitest) imprimem a linha que falhou e um diff, o que ameniza o problema do "qual linha?". O smell ainda incomoda quando o teste mistura objetivos, tem um nome vago, itera sobre asserções em laço, as esconde atrás de helpers compartilhados ou roda em um ambiente onde só uma mensagem de resumo sobrevive.

## Reasons for the Problem

**Por que acontece**

* _Eager Test / reúso de fixture._ Uma configuração custosa tenta você a acumular verificações do tipo "já que estou aqui" em vez de escrever um segundo teste.
* _Verificação de objeto inteiro feita do jeito difícil._ Verificar um objeto campo a campo naturalmente produz uma longa sequência de asserções não documentadas.
* _Crescimento por copiar e colar._ Os testes acumulam asserções ao longo do tempo sem que ninguém os divida.
* _Ferramental histórico._ As asserções clássicas do xUnit reportavam apenas passou/falhou, então uma asserção sem rótulo não dava contexto algum na falha — a origem do smell original de Meszaros.
* _Pressão de prazo._ Um teste grande parece mais rápido de escrever do que vários testes focados.

**Por que prejudica**

* _Diagnosticabilidade / confiabilidade._ Segundo o testsmells.org, "múltiplas instruções de asserção em um método de teste sem uma mensagem descritiva impactam a legibilidade/compreensibilidade/manutenibilidade, pois não é possível entender o motivo da falha." Você gasta tempo localizando qual asserção disparou.
* _Defeitos ocultos (falsa confiança)._ Asserções fail-fast param na primeira falha, então as asserções posteriores nunca são executadas. Você corrige uma, roda de novo, encontra a próxima — vários bugs ficam mascarados, e um "verde depois de uma correção" parece mais seguro do que de fato é.
* _Legibilidade._ O teste deixa de documentar um único comportamento; sua intenção fica enterrada em uma lista, e um nome de teste genérico não acrescenta nada.
* _Manutenibilidade._ Não fica claro se uma nova verificação pertence a este teste ou a um novo, então a pilha continua crescendo e preocupações não relacionadas acabam acopladas.

## Treatment

Busque o princípio por trás de um Single-Condition Test: **cada teste verifica um comportamento e pode falhar por exatamente um motivo.**

1. **Divida por objetivo.** Quebre o teste abrangente em testes focados com nomes descritivos. O nome então _é_ a mensagem de falha.
2. **Condense verificações campo a campo em uma única asserção.** Use `toEqual` / `expect.objectContaining` / um snapshot revisado para que N asserções virem um único diff significativo.
3. **Quando o agrupamento for genuinamente coeso, rotule as asserções.** O `expect` do Jest/Vitest não tem argumento de mensagem, então use o parâmetro de mensagem do `node:assert`, o `expect(actual, message)` do Vitest ou o `jest-expect-message`.
4. **Quer que toda verificação rode e reporte em conjunto?** Prefira dividir; caso contrário, use asserções leves (`expect.soft` no Vitest) para que uma falha não esconda as demais.
5. **Proteja-se contra regressões** limitando o número de asserções por teste (veja os detectores).

Antes — assertion roulette:

```js
test('register user', () => {
  const res = register({ email: 'a@b.com', age: 36 });
  expect(res.ok).toBe(true);
  expect(res.user.email).toBe('a@b.com');
  expect(res.user.isAdult).toBe(true);
  expect(res.welcomeEmailSent).toBe(true);
});

```

Depois — um comportamento por teste, com uma asserção de objeto inteiro:

```js
describe('register', () => {
  it('accepts a valid adult signup', () => {
    expect(register({ email: 'a@b.com', age: 36 }).ok).toBe(true);
  });

  it('stores the normalized user record', () => {
    const { user } = register({ email: 'a@b.com', age: 36 });
    expect(user).toEqual(
      expect.objectContaining({ email: 'a@b.com', isAdult: true }),
    );
  });

  it('sends a welcome email on signup', () => {
    expect(register({ email: 'a@b.com', age: 36 }).welcomeEmailSent).toBe(true);
  });
});

```

Se você precisar manter um único teste, faça cada asserção ser autoexplicativa:

```js
import { strict as assert } from 'node:assert';
assert.equal(res.ok, true, 'registration should succeed');
assert.equal(res.welcomeEmailSent, true, 'welcome email should be sent');

```

## Detected by

- **eslint-jest** `jest/max-expects` — Sinaliza o indicador baseado em contagem do Assertion Roulette: reporta quando um teste excede N chamadas expect() (padrão 5). A documentação observa que mais asserções tendem a misturar múltiplos objetivos. (https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/max-expects.md)
- **eslint-vitest** `vitest/max-expects` — Equivalente no Vitest: impõe um número máximo de asserções expect() por teste, capturando testes que acumulam verificações em excesso. (https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/max-expects.md)
- **sonar** `java:S5961` — SonarSource 'Métodos de teste não devem conter asserções demais' — limita as asserções por teste (padrão 25 para JUnit/AssertJ), o indicador padrão de análise estática para esse smell. (https://rules.sonarsource.com/java/RSPEC-5961/)
