Skip to content
IRC-CodingIRC-Coding
Mutation TestingMutation ScoreCalidad de TestsCode CoverageUnit TestsPITStryker

Mutation Testing: ¿Qué tan buenos son tus tests?

Aprende Mutation Testing: mutantes, mutation score, limitaciones y herramientas. Evalúa la calidad de tus tests más allá de coverage.

S

schutzgeist

5 min read
Mutation Testing: ¿Qué tan buenos son tus tests?

Mutation Testing

Code Coverage indica qué proporción del código se ejecuta a través de los tests, pero no revela si esos tests realmente verifican la presencia de errores. Mutation Testing cierra esta brecha insertando pequeños cambios en el código fuente y comprobando si los tests los detectan. Cuando una mutación (una fuente de error artificial) sobrevive la ejecución de tests, es evidente que el test no es lo suficientemente exhaustivo.

En Resumen

  • Mutation Testing inserta errores artificiales en el código fuente.
  • El objetivo es medir la calidad de los tests, no solo su cobertura.
  • Mutation Score = mutantes eliminadas / todas las mutantes.
  • El alto costo computacional es el mayor desafío.

Descripción Técnica Compacta

En Mutation Testing se generan mutantes, que son versiones ligeramente modificadas del código de producción. Una mutante puede cambiar un operador aritmético, invertir una condición o manipular un valor de retorno. La suite de tests se ejecuta contra cada mutante. Si al menos un test falla, la mutante ha sido eliminada. Si todos los tests pasan, la mutante ha sobrevivido, lo que sugiere que los tests son débiles.

Mutation Score

El Mutation Score se calcula así:

Mutation Score = (Mutantes Eliminadas / Número Total de Mutantes) * 100

Un score alto significa que los tests detectan errores en el código de manera confiable. Un score bajo indica que aunque los tests se ejecutan, no realizan una verificación efectiva.

Tipos de Mutaciones

Operadores Aritméticos

int result = a + b;  // Mutante: a - b

Operadores Relacionales

if (x > 10) { ... }  // Mutante: x < 10

Valores de Retorno

return true;  // Mutante: return false;

Eliminación de Sentencias

System.out.println("log");  // Mutante: línea eliminada

Condiciones

if (a && b)  // Mutante: if (a || b)

Herramientas Importantes

  • PIT: Mutation Testing para Java y lenguajes de la JVM.
  • Stryker: Mutation Testing para JavaScript, TypeScript y C#.
  • MutPy: Mutation Testing para Python.
  • Cosmic Ray: Mutation Testing para Python.
  • Infection: Mutation Testing para PHP.

Ejemplo Práctico: Mutación Simple en Java

public class DiscountCalculator {
    public int calculate(int amount) {
        if (amount > 100) {
            return amount - 10;
        }
        return amount;
    }
}
@Test
public void testDiscountForLargeAmount() {
    DiscountCalculator calc = new DiscountCalculator();
    assertEquals(90, calc.calculate(100));  // Problema: valor límite 100 en lugar de 101
}

Una mutante cambia amount > 100 a amount >= 100. Para el valor de entrada 100, ambos casos resultan en 90. El test sobrevive la mutante, aunque la condición es diferente. Esto demuestra que el test no verifica correctamente el valor límite.

Ventajas y Desventajas

Ventajas

  • Mejor calidad de tests: Mide si los tests realmente verifican.
  • Menos falsos positivos en coverage: La cobertura por sí sola no es prueba de calidad.
  • Enfoque en áreas críticas: Los tests débiles se hacen visibles.
  • Tests mejores: Los desarrolladores se ven obligados a escribir assertions más exhaustivas.

Desventajas

  • Alto costo computacional: Muchas mutantes generan muchas ejecuciones de tests.
  • Mutantes equivalentes: Algunas mutaciones no cambian el comportamiento, pero no pueden ser detectadas automáticamente.
  • Larga duración: En proyectos grandes, Mutation Testing puede tomar horas.
  • Mantenimiento: Las nuevas mutantes deben regenerarse con los cambios de código.

Puntos Clave Relevantes para Exámenes

  • Definición y propósito de Mutation Testing.
  • Mutation Score y su cálculo.
  • Tipos de mutaciones.
  • Herramientas como PIT, Stryker y MutPy.
  • Diferencia entre Coverage y Mutation Testing.
  • Problemas de mutantes equivalentes.

Preguntas Típicas de Examen (con Respuesta Breve)

  1. ¿Qué es Mutation Testing? Un método que inserta errores artificiales en el código para medir la calidad de los tests.

  2. ¿Qué indica el Mutation Score? La proporción de mutantes que fueron detectadas y eliminadas por los tests.

  3. ¿Qué es una mutante equivalente? Una mutación que no cambia el comportamiento del programa, pero aun así no es eliminada.

  4. Menciona una herramienta de Mutation Testing. PIT, Stryker, MutPy o Infection.

  5. ¿Cuál es la diferencia entre Coverage y Mutation Testing? Coverage mide qué código se ejecuta. Mutation Testing verifica si los tests detectan errores reales.

Fuentes Principales

  1. https://pitest.org
  2. https://stryker-mutator.io
  3. https://en.wikipedia.org/wiki/Mutation_testing

Preguntas Frecuentes

¿Qué es una mutante?

Una mutante es una versión ligeramente modificada del código fuente que representa un error artificial.

¿Qué significa mutante eliminada?

Una mutante es eliminada cuando al menos un test falla después del cambio. Esto demuestra que el test detectó el error.

¿Qué es un buen Mutation Score?

Un score superior al 80 por ciento se considera bueno. Sin embargo, lo más importante es que los tests detecten los errores realmente críticos.

¿Por qué es Mutation Testing computacionalmente intensivo?

Por cada mutante, la suite de tests completa debe ejecutarse nuevamente. Con muchas mutantes y bases de código grandes, esto genera un esfuerzo de tiempo enorme.

¿Qué son mutantes equivalentes?

Las mutantes equivalentes modifican el código sin cambiar el comportamiento. No pueden ser detectadas automáticamente y distorsionan el Mutation Score.

¿Es Mutation Testing solo apropiado para Unit Tests?

Principalmente sí, porque los Unit Tests son aislados y rápidos. Para tests de integración, Mutation Testing es menos común por su tiempo de ejecución y complejidad.

¿Cuándo debe usarse Mutation Testing?

Es útil en áreas de código estables y críticas cuando la cobertura ya es alta, pero la calidad de los tests sigue siendo incierta.

¿Cuál es un anti-patrón típico de Mutation Testing?

Escribir tests con assertions que toleran casi cualquier cambio, porque son demasiado genéricos o débiles.

¿Puede Mutation Testing ejecutarse en la pipeline CI/CD?

Sí, pero debido al tiempo de ejecución, a menudo se ejecuta como un job separado nocturno o semanal, no en cada commit.

¿Qué es Stryker?

Stryker es un framework popular de Mutation Testing para JavaScript, TypeScript y C#.

¿Qué es PIT?

PIT es una herramienta ampliamente utilizada de Mutation Testing para Java y otros lenguajes basados en JVM.

¿Reemplaza Mutation Testing la Code Coverage?

No. Lo complementa midiendo la calidad de los tests. Ambas métricas juntas proporcionan una visión más completa.

¿Qué significa Mutation Operator?

Un Mutation Operator es una regla que describe cómo se modifica el código para generar una mutante, por ejemplo invertir un operador de comparación.

¿Cómo se puede reducir el tiempo de ejecución de Mutation Testing?

Mediante ejecución paralela, Mutation Testing incremental, enfoque en áreas de código críticas y exclusión de archivos triviales o generados.

¿Qué indica una mutante que sobrevive?

Una mutante que sobrevive indica que la suite de tests no detectó el error insertado. El test es entonces demasiado débil o verifica el comportamiento incorrecto.

Continuar en la Ruta de Aprendizaje de Software Testing

El siguiente artículo en la ruta de aprendizaje de Software Testing trata sobre Shift-Left Testing, cómo se colocan los tests más temprano en el proceso de desarrollo.

Volver al blog
Share:

Nächster Artikel in Calidad de Software

Weiterlesen
Test Driven Development: Ciclo Red-Green-Refactor

Entradas relacionadas