No, no todas valen lo mismo. La cobertura de líneas te dice cuántas sentencias se ejecutaron; la de ramas, cuántas decisiones tomaron ambos caminos; la de condiciones, cuántas subexpresiones booleanas se probaron en verdadero y en falso. Son tres metros distintos que suelen dar el mismo porcentaje pero miden cosas muy diferentes, y confundirlos es la razón por la que un "90 % de cobertura" tranquiliza a un equipo mientras los bugs siguen pasando. Este artículo separa los tres, muestra con código por qué el más fácil de subir es el que menos protege, y explica cuál mirar cuando quieres confiar en tu número.
La palabra "cobertura" suena a una sola cosa, y ahí empieza el malentendido. Es una familia de métricas de caja blanca: todas miden qué parte de la estructura interna del código tocaron tus pruebas, pero cada una define "tocar" de forma más exigente que la anterior. El estándar ISO/IEC/IEEE 29119-4 las cataloga como criterios de cobertura estructural, y el temario del ISTQB las trata como el termómetro de qué tan a fondo entró tu suite [1][2]. El problema no es la métrica: es creer que un número alto en la más barata equivale a un software bien probado.
01 · el metro fácilCobertura de líneas: cuenta sentencias, no lógica
La cobertura de líneas (o de sentencias) responde a una pregunta simple: de todas las líneas ejecutables del código, ¿cuántas corrió al menos una prueba? Si tienes cien líneas y tus pruebas ejecutaron noventa, tienes 90 % de cobertura de líneas. Es la métrica que casi todas las herramientas muestran por defecto, y también la más fácil de inflar.
El defecto es de fondo, no de calibración. Una línea "cubierta" solo significa que el intérprete pasó por encima de ella, no que se haya comprobado que hace lo correcto ni que se probaran sus dos posibles desenlaces. Una condición sin bloque else puede marcar el 100 % de líneas sin haber probado nunca qué ocurre cuando esa condición es falsa, porque no hay ninguna línea que ejecutar en el caso falso. La línea existió, se ejecutó una vez por el lado verdadero, y el metro quedó satisfecho.
Cubrir una línea prueba que el código pasó por ahí. No prueba que pasó por ahí bien, ni que probaste el camino que no tomó.
02 · el metro honestoCobertura de ramas: cada decisión, en sus dos salidas
La cobertura de ramas (o de decisiones) sube el listón. Ya no cuenta líneas: cuenta las salidas de cada punto de decisión. Un if tiene dos ramas, verdadero y falso; un bucle tiene la rama que entra y la que no; un switch tiene una por caso. Para llegar al 100 % de ramas, tus pruebas tienen que haber hecho que cada decisión tomara ambos caminos al menos una vez.
Ese cambio de foco es exactamente lo que le faltaba a la Figura 1. La misma función con la misma prueba única marca 100 % de líneas y solo 50 % de ramas, porque la rama "no es VIP" nunca se ejecutó. La cobertura de ramas obliga a añadir el segundo caso, y con él aparece el escenario donde de verdad se esconden los errores: el camino que el programador dio por trivial y no probó. Por eso el ISTQB señala que la cobertura de decisiones es más fuerte que la de sentencias, y que el 100 % de la primera garantiza el 100 % de la segunda, pero no al revés [2].
Estos criterios están anidados: cubrir todas las ramas implica cubrir todas las líneas, pero no al contrario. Por eso comparar "90 % de líneas" contra "90 % de ramas" entre dos proyectos es engañoso: el segundo 90 % costó más y protege más. Cuando alguien te da un porcentaje de cobertura, la primera pregunta no es cuánto, sino de qué.
Aun así, la cobertura de ramas tiene un punto ciego propio, y es sutil. Trata cada decisión como una caja cerrada: le basta con que la condición entera resulte verdadera una vez y falsa otra. No mira qué hay dentro de esa condición. Y cuando la condición combina varias comprobaciones con y / o, ahí es donde el metro honesto todavía se queda corto.
03 · el metro finoCobertura de condiciones: dentro del booleano
Considera una decisión compuesta: si (edad >= 18 y tienePermiso). La cobertura de ramas se conforma con dos casos que hagan la expresión completa verdadera y falsa. Puedes lograrlo probando solo (20, verdadero) y (15, falso). En ambos casos la variable tienePermiso se movió a la vez que la edad: nunca comprobaste qué pasa con un mayor de edad sin permiso, ni con un menor con permiso. La rama quedó "cubierta" y la mitad de la lógica interna, sin tocar.
La cobertura de condiciones ataca justo eso: exige que cada subexpresión booleana se evalúe en verdadero y en falso por separado. Su variante rigurosa, la MC/DC (Modified Condition/Decision Coverage), va más allá: pide demostrar que cada condición, por sí sola, puede cambiar el resultado de la decisión completa. No es un capricho académico. La aviónica crítica lo exige por norma: el estándar DO-178C obliga a MC/DC para el software de nivel A, ese cuya falla puede costar vidas [3]. Cuando el bug no se paga en un reintento sino en un accidente, el metro fino deja de ser opcional.
04 · el número que sí sirveQué mirar y qué no perseguir
De aquí sale una conclusión incómoda para quien colecciona porcentajes: la cobertura alta es necesaria pero no suficiente. Un 100 % de líneas convive con lógica sin probar; un 100 % de ramas es mucho más difícil de fingir; MC/DC es casi imposible sin haber pensado cada decisión. Pero ninguno verifica que la salida sea correcta: miden qué código se ejecutó, no si el resultado fue el esperado. Una suite puede recorrer el 100 % de las ramas con asserts vacíos y no atrapar un solo defecto.
Por eso perseguir "el 100 %" como meta suele empeorar el software: se escriben pruebas de relleno que tocan líneas sin comprobar nada, solo para mover el número. La cobertura funciona al revés, como detector de huecos: la lees para hallar qué partes nadie probó todavía, y decides si ese hueco importa. Un camino de manejo de error sin cubrir es una alarma; una rama de logging sin cubrir, casi nunca. Qué cubrir a fondo lo pone el riesgo, no la vanidad del porcentaje.
La cobertura no te dice si tu software está bien probado. Te dice dónde con seguridad no lo está. Ese es su verdadero poder.
Así que la próxima vez que alguien celebre un número de cobertura, haz las dos preguntas que lo desarman: ¿de qué es esa cobertura, líneas o ramas? Y ¿los huecos que quedan son de código que no importa, o justo del que sí? La respuesta separa un equipo que entiende su métrica de uno que solo la mira subir. En Qirava tratamos la cobertura como lo que es: un mapa de lo que falta, no un trofeo de lo que sobra.
Fuentes
- ISO/IEC/IEEE 29119-4:2021. Software and systems engineering. Software testing. Part 4: Test techniques. International Organization for Standardization. (Define los criterios de cobertura estructural: sentencia, decisión/rama y condición.)
- ISTQB (2018). Certified Tester Foundation Level Syllabus, v3.1. International Software Testing Qualifications Board. Sección sobre técnicas de caja blanca y cobertura de sentencias y decisiones.
- RTCA DO-178C / EUROCAE ED-12C (2011). Software Considerations in Airborne Systems and Equipment Certification. RTCA Inc. (Exige Modified Condition/Decision Coverage, MC/DC, para software de nivel de aseguramiento A.)
- Myers, G. J., Sandler, C. & Badgett, T. (2011). The Art of Software Testing, 3.ª ed. John Wiley & Sons. Capítulo sobre pruebas de caja blanca y cobertura lógica.