java - ramas - Cobertura de la rama de eclemma para el interruptor: 7 de 19 perdido
rama legislativa definicion (2)
Tengo este sistema de cambio y estoy usando eclemma para probar la cobertura de la sucursal. Estamos obligados a tener al menos el 80% en la cobertura de sucursales para todo, por lo que estoy tratando de probar lo más posible. Sin embargo, eclemma me dice que este sistema de cambio no está completamente probado en términos de cobertura de sucursales.
pos = p.getCurrentPosition().substring(0, 1);
switch (pos) {
case "G":
goalkeepers++;
break;
case "D":
defense++;
break;
case "M":
midfield++;
break;
case "F":
offense++;
break;
case "S":
substitutes++;
break;
case "R":
reserves++;
break;
}
Utilicé pruebas de JUnit directas para analizar cada uno de estos casos. Todavía el eclemma marca esto como amarillo y dice "7 de 19 ramas faltaron". Yo diría que solo hay 7 formas de pasar por este sistema de conmutación (los 6 casos individuales + todos indefinidos).
Intenté buscar preguntas similares en el desbordamiento de pila. Algunos de ellos tenían como soluciones para utilizar si / else para una cobertura completa. No estoy seguro si esta es la única forma posible de obtener esta cobertura.
¿Alguien puede explicar de dónde provienen estas 19 sucursales y cómo puedo probar estas 7 restantes para obtener una cobertura de sucursal del 100% en este caso de conmutador?
Consulte el siguiente enlace: http://sourceforge.net/p/eclemma/discussion/614869/thread/80e770df/
A continuación se muestra un fragmento del enlace anterior:
Esto para un ejemplo que tiene un interruptor con 3 casos:
Esta es una observación bastante interesante. Al observar el código de bytes, se puede ver cómo el compilador de Java maneja el conmutador en cadenas. En realidad es un proceso de 3 pasos:
- Encienda el código hash (3 ramas, 1 por defecto)
- Para cada código hash haga un igual (3 * 2 ramas)
- Haga un cambio final para la ejecución real de los casos (3 sucursales, 1 por defecto)
Así que tenemos un total de 14 sucursales que parecen extrañas desde el punto de vista del código fuente. Lo que parece aún más extraño es que te estás perdiendo tres. La explicación es el paso 2, donde el método de igualdad se aplica adicionalmente después del código hash. Para cubrir estas ramas también necesitarías encontrar otras cadenas con el mismo código hash. Esto es definitivamente algo que podría filtrarse de los informes de cobertura en futuras versiones de JaCoCo:
https://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions
El compilador de Java traduce el código de la caja del conmutador a un tableswitch
oa un lookupswitch
. El tableswitch
se utiliza cuando solo hay unos pocos huecos entre los diferentes casos. De lo contrario, se utiliza el lookupswitch
.
En su caso, se usa un tableswitch
porque los códigos hash de sus casos están muy espaciados (a diferencia del código al que hace referencia Owaism):
16: tableswitch { // 68 to 83
68: 111 // ''D''
69: 183
70: 141 // ''F''
71: 96 // ''G''
72: 183
73: 183
74: 183
75: 183
76: 183
77: 126 // ''M''
78: 183
79: 183
80: 183
81: 183
82: 171 // ''R''
83: 156 // ''S''
default: 183
}
Los números a la izquierda de los dos puntos son los códigos hash ordenados y los espacios vacíos entre ellos, los números a la derecha son los destinos de salto. (En Java, el código hash de un carácter es su valor ASCII).
68
es el código hash de "D" (el más bajo), y 83
es el código hash de "S" (el más alto). 69
es el valor de uno de los huecos entre los casos reales y saltará al caso predeterminado.
Sin embargo, asumo que EclEmma excluye estas ramas del cálculo de cobertura de un tableswitch
de tableswitch
(reduciría la cobertura aún más debido a las brechas). Así que tenemos 0 ramas (contadas) todavía.
A continuación, se realiza una comparación igual del valor de la cadena en cada destino de salto (excepto en el del caso predeterminado). Como su caja de conmutación consta de 6 casos, tenemos 6 seis destinos de salto con una comparación de iguales.
El código de bytes de la comparación para el caso "G" está debajo:
96: aload_3
97: ldc #10
99: invokevirtual #11 java/lang/Object;)Z
102: ifeq 183
105: iconst_0
106: istore 4
108: goto 183
111: aload_3
EclEmma cuenta dos ramas: o la cadena de entrada y la cadena de caso son iguales o no lo son. Por lo tanto, tenemos 6 * 2 ramas para las comparaciones. (El caso predeterminado no se ramifica.)
A continuación, si las dos cadenas son iguales, se almacenará el índice del caso (líneas de código de bytes 105-106
para el caso "G"). Luego se ejecutará un salto al segundo tableswitch
. De lo contrario, el salto se ejecutará directamente.
185: tableswitch { // 0 to 5
0: 224
1: 237
2: 250
3: 263
4: 276
5: 289
default: 299
}
Este interruptor opera en el índice de caso previamente almacenado y salta al código en el caso (caso "G" tiene índice 0
, el caso predeterminado tiene -1
). EclEmma cuenta con 7 sucursales (6 casos más el caso predeterminado).
En consecuencia, tenemos 0 ramas contadas en el primer tableswitch
, 12 sucursales en las comparaciones de equals
y otras 7 sucursales en el segundo tableswitch
. Con todo, esto resulta en 19 ramas.
Sus pruebas no cubren ninguna de las 6 ramas diferentes. Para cubrir esto, necesitaría encontrar una cadena para cada caso que no sea igual a la condición del caso pero que tenga el mismo código hash. Es posible, pero definitivamente no sensible ...
Probablemente, el conteo de sucursales de EclEmma se ajustará en el futuro.
Además, creo que no tiene un caso de prueba que no coincida con ninguno de los casos (por lo tanto, el caso predeterminado (implícito) no está cubierto).