---
title: "Dependencia del orden de los tests"
type: "test-smell"
slug: "test-order-dependency"
url: "http://localhost:3000/es/test-smells/test-order-dependency.md"
category: "Olores erráticos"
description: "Un test pasa o falla según qué otros tests se hayan ejecutado antes, porque los tests filtran y dependen de estado mutable compartido en lugar de que cada uno configure y desmonte su propio fixture."
---
# Dependencia del orden de los tests

> Un test pasa o falla según qué otros tests se hayan ejecutado antes, porque los tests filtran y dependen de estado mutable compartido en lugar de que cada uno configure y desmonte su propio fixture.

## Signs and Symptoms

El resultado de un test depende del **orden** en que se ejecuta la suite, no solo del código bajo prueba. Se supone que cada test es autocontenido, pero aquí un test depende de forma silenciosa de los efectos secundarios dejados por otro.

Señales reveladoras:

* Un test **pasa en la suite completa pero falla al ejecutarse solo** (con `.only`, un filtro por nombre o ejecutando únicamente ese archivo). Meszaros lo llama _Lonely Test_.
* Los tests **se rompen al barajarlos (shuffle), particionarlos (shard) o paralelizarlos**, o tras actualizar un ejecutor que cambia el orden por defecto.
* **Eliminar, omitir o reordenar** un test hace que falle otro aparentemente no relacionado.
* Un fallo desencadena una **cascada** de fallos posteriores (los _Interacting Tests_ de Meszaros; la _Test Run War_ de van Deursen cuando los ejecutores en paralelo chocan sobre un fixture compartido).
* Los tests son **intermitentemente inestables (flaky)** sin ningún cambio de código: la dependencia del orden es una de las causas raíz más habituales de los flaky tests.

La pista estructural es el **estado mutable compartido** que se lee entre tests: variables a nivel de módulo/`static`/globales, un `beforeAll` que rellena el estado una sola vez, o un recurso externo sin reiniciar (filas de BD, archivos, cachés, variables de entorno, temporizadores falsos, mocks).

```js
let users = []; // estado compartido a nivel de módulo

test('creates a user', () => {
  users.push({ id: 1, name: 'Ada' });
  expect(users).toHaveLength(1);
});

// En verde solo porque el test anterior se ejecutó primero y mutó `users`.
// Ejecuta este test solo, o cambia el orden, y falla.
test('finds the created user', () => {
  expect(users.find(u => u.name === 'Ada')).toBeDefined();
});

```

## Reasons for the Problem

**Por qué ocurre**

* Un **Shared Fixture** (configurado una sola vez en `beforeAll`, una variable con ámbito de módulo, un `static` de clase o una base de datos/archivo real) es mutado por los tests y nunca se reinicia entre ellos, de modo que cada test hereda los restos del anterior.
* Comodidad y rapidez: se reutiliza una configuración costosa o se «construye sobre» los datos del test anterior para evitar recrearlos (a veces formalizado como _Chained Tests_).
* La dependencia es **accidental e invisible**: nada en el código del test declara «ejecútame después de aquel», así que sobrevive hasta que cambia el orden.

**Por qué es perjudicial**

* **Fiabilidad / falsa confianza.** La suite está en verde por la suerte del orden. Reordena, paraleliza o ejecuta un subconjunto y los tests fallan (o, peor aún, una regresión real se oculta porque un test anterior dejó por casualidad un estado «correcto»). Los tests dependientes del orden son una de las principales fuentes de _flaky tests_.
* **Mantenibilidad.** No puedes ejecutar, depurar ni volver a ejecutar de forma aislada un único test que falla: el test prerrequisito debe ejecutarse primero. Añadir, eliminar o reordenar tests tiene efectos fantasma a distancia.
* **Legibilidad.** Un test ya no documenta un comportamiento con entradas explícitas; entenderlo requiere leer lo que se ejecutó antes (un _Mystery Guest_ oculto en el orden de ejecución).
* **Bloquea el paralelismo y la selección.** El particionado de tests (sharding), los ejecutores en paralelo y las herramientas de impacto/selección de tests asumen independencia; el acoplamiento por orden los vuelve inseguros.

## Treatment

Haz que cada test sea **independiente**: configura todo lo que necesita, hace sus aserciones y limpia, de modo que produzca el mismo resultado en cualquier orden, solo o dentro de una suite.

1. **Dale a cada test un Fresh Fixture.** Saca la configuración compartida de `beforeAll` a `beforeEach` (o constrúyela dentro del test), de modo que el estado se reconstruya por test en lugar de acumularse.
2. **Elimina el estado mutable compartido.** No leas ni escribas variables a nivel de módulo, `static` o globales entre tests. Construye los objetos localmente; pasa los datos de forma explícita.
3. **Reinicia los recursos externos en el teardown.** Revierte la BD (una transacción por test) o usa datos únicos por test; elimina los archivos temporales; restaura las variables de entorno, las globales y los temporizadores falsos; limpia los mocks (`jest.clearAllMocks()` / `vi.restoreAllMocks()`, `jest.resetModules()`). Prefiere un teardown automático/garantizado a una limpieza manual.
4. **Demuestra la independencia aleatorizando el orden.** Este es el verdadero detector: es una propiedad dinámica, no algo que un linter pueda ver:
  * Jest: `--randomize` / `randomize: true`.
  * Vitest: `sequence.shuffle` (config o `--sequence.shuffle`).
  * pytest: `pytest-randomly` o `pytest-random-order`.
  * Maven Surefire: `-Dsurefire.runOrder=random`. Ejecuta también un subconjunto/un solo test en CI, para que afloren los _Lonely Tests_.
5. **Si realmente se necesita una configuración compartida** (un fixture costoso y de solo lectura), hazlo **inmutable** y compártelo en solo lectura, o usa como último recurso una suite de _Chained Test_ deliberadamente documentada, nunca una dependencia accidental. Ten en cuenta que la regla `no-hooks` de `eslint-plugin-jest`/`eslint-plugin-vitest` puede desalentar los hooks de setup/teardown que tienden a fomentar el estado compartido, pero no detecta por sí misma la dependencia del orden.

```js
// Antes — dependiente del orden: el test 2 necesita los restos del test 1
let users = [];
test('creates a user', () => {
  users.push({ id: 1, name: 'Ada' });
  expect(users).toHaveLength(1);
});
test('finds the created user', () => {
  expect(users.find(u => u.name === 'Ada')).toBeDefined();
});

// Después — cada test posee su propio fixture
function makeRepo(seed = []) {
  return { users: [...seed] };
}

test('creates a user', () => {
  const repo = makeRepo();
  repo.users.push({ id: 1, name: 'Ada' });
  expect(repo.users).toHaveLength(1);
});

test('finds an existing user', () => {
  const repo = makeRepo([{ id: 1, name: 'Ada' }]); // configura su propia precondición
  expect(repo.users.find(u => u.name === 'Ada')).toBeDefined();
});

```
