Logotipo de ConstructiCat
CodeBust.
Explorar la sección ▾

Ignored Test.

Una prueba que está confirmada en la base de código pero que nunca se ejecuta porque se ha omitido, desactivado o comentado, dando la apariencia de cobertura sin verificar nada en realidad.

##Signos y síntomas

Una prueba existe en la suite pero tiene su ejecución impedida de forma permanente. Sigue contando como una "prueba" en el fichero, pero no aporta ninguna verificación. Vigila los marcadores de skip/ignore, los bloques con prefijo x y el código de prueba enterrado en comentarios, a menudo acompañados de una excusa vaga como "flaky" o "fix later".

// modificadores skip/disabled: nunca se ejecutan
describe.skip('checkout flow', () => { /* ... */ });
it.skip('applies the discount', () => { /* ... */ });

// con prefijo x (jasmine/jest/mocha): mismo efecto
xit('rejects negative amounts', () => { /* ... */ });
xdescribe('payments', () => { /* ... */ });

// prueba comentada: invisible para el runner Y para el reporter
// it('retries on 503', async () => {
//   await expect(client.fetch()).resolves.toBeOk();
// });
// JUnit: @Ignore / @Disabled con un motivo poco riguroso
@Ignore("disabled for now as this test is too flaky")
@Test public void peerPriority() { /* ... */ }

Señales reveladoras en el informe de pruebas: un recuento de "skipped"/"pending" distinto de cero que nadie mira, suites que han encogido en silencio con el tiempo y omisiones sin incidencia vinculada ni caducidad. Los return condicionales al principio de una prueba (if (process.platform === 'win32') return;) son una variante más astuta que oculta por completo la omisión a los contadores de omisiones.

No toda marca es este olor. test.todo('handles expired coupons — PAY-412') no tiene cuerpo, aparece en el informe como todo (nunca como aprobada) y apunta a un ticket: es un marcador de posición honesto y visible. Una prueba con el cuerpo vacío que se reporta en verde es otro problema: la prueba vacía.

##Causas del problema

Por qué ocurre

  • Una prueba empezó a fallar (una regresión real, una dependencia temporal inestable, un cambio de entorno o de versión) y omitirla fue la forma más rápida de conseguir una build verde o desbloquear un merge.
  • Una prueba se escribió antes que la implementación, se aparcó con xit/it.skip sin ticket y nunca se retomó. (Un test.todo vinculado a un ticket al menos sigue visible en cada informe.)
  • Las migraciones (nuevo framework, runtime o API) rompieron la prueba y se aparcó "temporalmente".
  • La omisión iba a durar una tarde; sin recordatorio, caducidad ni incidencia de seguimiento, se vuelve permanente.

Por qué es perjudicial

  • Falsa confianza. Una prueba omitida parece cobertura en el fichero y en el diff del PR, pero no ejercita nada. El camino de código que decía proteger queda ahora desprotegido, y todo el mundo da por hecho que es seguro.
  • Putrefacción (bit rot). Una prueba omitida se sigue compilando y comprobando sus tipos, pero nunca se ejecuta, así que nadie nota cuándo sus fixtures, valores esperados y suposiciones dejan de corresponder al código. Una prueba comentada es peor: ni siquiera se compila, así que los cambios de API la rompen en silencio y nadie se entera hasta que alguien la descomenta. Cuanto más tiempo permanecen, más se alejan de la realidad, hasta que reactivarlas cuesta más que reescribirlas.
  • Regresiones ocultas. El error o el comportamiento inestable que motivó la omisión sigue ahí: simplemente se ha silenciado. Omitir trata el síntoma (una barra roja) en lugar de la enfermedad.
  • Ruido y erosión. Los recuentos permanentes de "omitidas" enseñan al equipo a ignorar el informe de pruebas, lo que deja que se cuelen nuevas omisiones sin que nadie las note. El código de prueba muerto y comentado también añade carga de lectura y mantenimiento sin ningún beneficio.

##Tratamiento

Trata cada prueba ignorada como una decisión que debe tomarse ahora, no aplazarse indefinidamente.

  1. Clasifica cada omisión. Para cada prueba desactivada o comentada, decide: arreglarla, eliminarla o ponerla en cuarentena con una caducidad y una incidencia de seguimiento. "Dejarla omitida para siempre" no es una opción. Un test.todo que nombra un ticket ya es un marcador de posición honesto: mantenlo solo mientras ese ticket siga abierto.
  2. Arréglala y reactívala si el comportamiento sigue importando. Si la prueba es inestable, corrige la inestabilidad (controla el tiempo, la aleatoriedad, la asincronía y el estado compartido) en lugar de omitirla.
  3. Elimínala si la funcionalidad ya no existe o la prueba está obsoleta. Una prueba eliminada es honesta; una omitida miente. El control de versiones la recuerda por si alguna vez la necesitas de vuelta, así que nunca comentes una prueba en lugar de eliminarla.
  4. Si debes omitir temporalmente, hazlo de forma visible y acotada en el tiempo: incluye siempre un motivo y un enlace de seguimiento, y prefiere un mecanismo que aparezca en los informes y falle una vez pasado el plazo, para que la omisión no pueda pudrirse.
  5. Detén la hemorragia con lint/CI. Activa una regla de "no disabled tests" para que las nuevas omisiones se detecten en la revisión, y trata el recuento de omisiones existente como un backlog que reducir hasta cero.
// antes: silenciosa, permanente, sin seguimiento
it.skip('refunds the full amount on cancel', async () => {
  await expect(refund(order)).resolves.toEqual({ amount: 100 });
});

// después: arreglada y ejecutándose de nuevo (causa raíz: total en coma flotante)
it('refunds the full amount on cancel', async () => {
  await expect(refund(order)).resolves.toEqual({ amount: 100 });
});

// solución intermedia aceptable: visible, atribuida y con caducidad
it.skip('refunds the full amount on cancel — flaky clock, see JIRA-1234 (remove by 2027-03-01)', async () => {
  /* ... */
});
// antes
@Ignore("too flaky")
@Test public void peerPriority() { ... }

// después: corrige la dependencia temporal y reactívala, o elimínala si está obsoleta
@Test public void peerPriority() { ... }

##Detectado por