ConstructiCat Logo
CodeBust.
Browse section ▾

Aserción Redundante.

Una aserción redundante compara un valor consigo mismo o con un literal que es igual por construcción, por lo que su resultado es fijo y nunca puede fallar realmente ni detectar una regresión.

##Signs and Symptoms

Una aserción es redundante cuando su resultado se decide antes incluso de que se ejecute el código bajo prueba: los operandos esperado y real son el mismo valor, o ambos son literales que se sabe que son iguales (o desiguales). El catálogo xUnit/Test Smells (Peruma et al.) la define como "un método de prueba que contiene una sentencia de aserción en la que los parámetros esperado y real son el mismo", y señala que la aserción es, por tanto, "o bien siempre verdadera o bien siempre falsa".

Cómo detectarlo:

  • Un assertEquals/toBe/toEqual cuyos dos argumentos son la misma expresión o variable.
  • Un literal booleano afirmado contra sí mismo, p. ej. assertTrue(true) o expect(true).toBe(true).
  • Una comparación que el compilador/linter puede demostrar que es constante, como expect(x === x).toBe(true).
  • Una "comprobación de cordura" que reafirma una constante que acabas de declarar en lugar de ejercitar el sistema.
// Olor: el resultado es fijo, el código bajo prueba nunca interviene
test('user is active', () => {
  expect(true).toBe(true);            // siempre pasa
  const status = 'active';
  expect(status).toBe('active');      // reafirma el literal, no prueba nada
  expect(user.id).toEqual(user.id);   // valor comparado consigo mismo
});

Una señal fiable: puedes eliminar por completo el código de producción y la aserción sigue pasando en verde.

##Reasons for the Problem

Por qué ocurre

  • Restos de depuración. El catálogo señala explícitamente que este olor "lo introducen los desarrolladores con fines de depuración y luego lo olvidan": un marcador de posición assertTrue(true) codificado de forma fija que sobrevive hasta el commit.
  • Deriva por copiar‑pegar / refactorización. Se sustituye una variable en ambos lados de un assertEquals, o se renombra un valor bajo prueba de modo que el esperado y el real colapsan en el mismo símbolo.
  • Tautología por construcción. Afirmar un valor contra el literal del que acaba de ser asignado, en lugar de contra una expectativa derivada de forma independiente.
  • Teatro de cobertura. Se añade una aserción solo para satisfacer reglas del tipo "toda prueba debe afirmar algo", sin comprobar nada significativo.

Por qué es perjudicial

  • Falsa confianza. La prueba está permanentemente en verde y cuenta para el tamaño de la suite y la cobertura, pero no verifica nada. No puede detectar una regresión, así que enmascara huecos en la red de seguridad.
  • La fiabilidad carece de sentido. Una prueba que nunca puede fallar no aporta ninguna señal; una que siempre es falsa es peso muerto que se ignora o se skipea.
  • Legibilidad. Los lectores malgastan esfuerzo reconstruyendo el comportamiento previsto a partir de una aserción que afirma una tautología; la prueba ya no documenta un requisito.
  • Mantenibilidad. Las aserciones redundantes acumulan ruido, inflan las métricas y erosionan la confianza en la suite, animando a la gente a dejar de leer las aserciones con atención.

##Treatment

Reemplaza la tautología por una comprobación que vincule un valor esperado conocido de forma independiente con el resultado real producido por el sistema bajo prueba.

Pasos:

  1. Identifica la aserción de resultado fijo: el mismo operando en ambos lados, o dos literales iguales.
  2. Determina la verdadera intención. ¿Qué comportamiento se suponía que verificaba esta prueba? Si ninguno, la aserción (o toda la prueba) está muerta y debería eliminarse.
  3. Afirma sobre la salida del SUT, no sobre la entrada. Alimenta el sistema con una entrada real y compara su resultado calculado con un valor esperado codificado de forma fija y calculado a mano, no con una de sus propias entradas/variables.
  4. Mantén esperado/real diferenciados. Asegúrate de que el operando esperado sea una constante que escribiste a propósito y de que el operando real sea el valor de retorno del código bajo prueba (también corrige el olor relacionado de orden de argumentos incorrecto).
  5. Vuelve a ejecutar con la implementación rota (mútala) para confirmar que la aserción realmente puede fallar.
// Antes — redundante: el resultado es fijo
test('discount', () => {
  const total = 100;
  expect(total).toBe(100);          // reafirma el literal
  expect(applyDiscount).toBe(applyDiscount); // valor frente a sí mismo
});

// Después — significativo: entrada conocida -> salida esperada de forma independiente
test('applies a 10% discount', () => {
  expect(applyDiscount(100, 0.1)).toBe(90); // resultado del SUT frente a expectativa calculada a mano
});

Si quedó un marcador de posición como assertTrue(true) de la depuración, elimínalo; si sustituía a una comprobación real, escribe esa comprobación.

##Detected by

  • sonar javascript:S5863A las aserciones no se les debe pasar dos veces el mismo argumento
  • sonar java:S5863A las aserciones no se les debe pasar dos veces el mismo argumento
  • eslint no-constant-binary-expressionProhibir expresiones donde la operación no afecta al valor (marca autocomparaciones / aserciones siempre verdaderas como assert(a === a))