¿Qué es un% de cobertura de código razonable para las pruebas unitarias (y por qué)? [cerrado]

605

Si tuviera que exigir un porcentaje mínimo de cobertura de código para las pruebas unitarias, tal vez incluso como un requisito para comprometerse con un repositorio, ¿cuál sería?

Por favor explique cómo llegó a su respuesta (ya que si todo lo que hizo fue elegir un número, entonces podría haberlo hecho yo solo;)

cordura
fuente
Hoy en día, muchos IDE vienen con resaltado de cobertura, asegúrese de cubrir las partes más importantes del código al menos que esté pensando en alcanzar un porcentaje dado.
Todo será el
44
El símbolo% es olor a código para las métricas (también% es olor a mierda en general)
Hernán Eche
Las pruebas unitarias por definición pueden ser métodos individuales, clases completas o módulos completos. Incluso si prueba todos los métodos, es posible que no pruebe todas las rutas o todas las combinaciones que encontrará un usuario. La situación se vuelve más compleja con la declaración, la cobertura de sucursales y los MCDC.
Ska
¿Por qué esta pregunta no se elimina o no se edita correctamente? Reunió mucho interés pero es totalmente engañoso.
Ska

Respuestas:

1391

Esta prosa de Alberto Savoia responde precisamente esa pregunta (¡de una manera muy entretenida!):

http://www.artima.com/forums/flat.jsp?forum=106&thread=204677

Testivus en cobertura de prueba

Una mañana temprano, un programador le preguntó al gran maestro:

“Estoy listo para escribir algunas pruebas unitarias. ¿Qué código de cobertura debo buscar?

El gran maestro respondió:

"No se preocupe por la cobertura, simplemente escriba algunas buenas pruebas".

El programador sonrió, hizo una reverencia y se fue.

...

Más tarde ese día, un segundo programador hizo la misma pregunta.

El gran maestro señaló una olla de agua hirviendo y dijo:

"¿Cuántos granos de arroz debo poner en esa olla?"

El programador, confundido, respondió:

“¿Cómo puedo decírtelo? Depende de cuántas personas necesita alimentar, qué tan hambrientos están, qué otra comida está sirviendo, cuánto arroz tiene disponible, etc. ”.

"Exactamente", dijo el gran maestro.

El segundo programador sonrió, hizo una reverencia y se fue.

...

Hacia el final del día, llegó un tercer programador y le hizo la misma pregunta sobre la cobertura del código.

"¡Ochenta por ciento y nada menos!" Respondió el maestro con voz severa, golpeando su puño sobre la mesa.

El tercer programador sonrió, hizo una reverencia y se fue.

...

Después de esta última respuesta, un joven aprendiz se acercó al gran maestro:

“Gran maestro, hoy te escuché responder la misma pregunta sobre la cobertura del código con tres respuestas diferentes. ¿Por qué?"

El gran maestro se levantó de su silla:

"Ven a tomar un té fresco conmigo y hablemos de ello".

Después de llenar sus tazas con té verde caliente humeante, el gran maestro comenzó a responder:

“El primer programador es nuevo y recién está comenzando con las pruebas. En este momento tiene mucho código y no tiene pruebas. Tiene un largo camino por recorrer; centrarse en la cobertura del código en este momento sería deprimente y bastante inútil. Es mejor acostumbrarse a escribir y ejecutar algunas pruebas. Puede preocuparse por la cobertura más tarde ".

“El segundo programador, por otro lado, tiene bastante experiencia tanto en programación como en pruebas. Cuando le respondí preguntándole cuántos granos de arroz debería poner en una olla, le ayudé a darse cuenta de que la cantidad de pruebas necesarias depende de una serie de factores, y ella conoce esos factores mejor que yo; después de todo, es su código. . No hay una respuesta única y simple, y es lo suficientemente inteligente como para manejar la verdad y trabajar con eso ”.

"Ya veo", dijo el joven aprendiz, "pero si no hay una respuesta simple, entonces ¿por qué respondiste al tercer programador 'Ochenta por ciento y nada menos'?"

El gran maestro se rió tan fuerte y fuerte que su barriga, evidencia de que bebió más que té verde, se dejó caer de arriba abajo.

"El tercer programador solo quiere respuestas simples, incluso cuando no hay respuestas simples ... y luego no las sigue de todos modos".

El joven aprendiz y el gran maestro canoso terminaron de beber su té en silencio contemplativo.

Jon Limjap
fuente
6262
Suena como un argumento en contra del concepto general de cobertura de código, como una métrica para evaluar la utilidad de las pruebas unitarias. Estoy seguro de que todos están de acuerdo que no es una métrica perfecta, pero la experiencia personal debe mostrar es de esperar una cierta correlación entre CC% y la eficacia de prueba de unidad ...
cordura
16
cordura: su declaración se refleja precisamente en la respuesta al "segundo desarrollador". La experiencia personal debería dictarlo.
Jon Limjap
167
Respuesta perfecta. Las métricas no hacen un buen código. Puede escribir código malo con una cobertura del 100% y no hace que el código funcione bien. +1 de mi parte, lástima que no puedo subir más :)
Rob Cooper
15
4 años después, y sigue siendo útil. Acabo de mencionar esto a dos de mis colegas esta mañana.
SickHippie
99
Para mí, esta anécdota representa una visión idealista. En el mundo real de los equipos de proyecto con prioridades competitivas, la cobertura de código aumenta al 0%. Necesitamos un número requerido para construir el hábito de prueba de unidad dentro del equipo. Llegué a esta pregunta en busca de orientación para determinar ese número para un área con la que no estoy muy familiarizado, y esto realmente no es de ninguna ayuda. Sin embargo, me alegra que las personas en otros escenarios lo encuentren útil.
samspot
86

La cobertura de código es una métrica engañosa si su objetivo es obtener una cobertura del 100% (en lugar de probar el 100% de todas las funciones).

  • Podrías obtener un 100% golpeando todas las líneas una vez. Sin embargo, aún podría perderse la prueba de una secuencia particular (ruta lógica) en la que se golpean esas líneas.
  • No pudo obtener un 100%, pero aún así ha probado todas sus rutas de código utilizadas al 80% / frecuencia. Tener pruebas que prueben cada 'throw ExceptionTypeX' o protección de programación defensiva similar que haya puesto es un 'agradable', no un 'must have'

Así que confía en ti mismo o en tus desarrolladores para ser minucioso y cubrir cada ruta a través de su código. Sé pragmático y no persigas la mágica cobertura del 100%. Si TDD su código, debería obtener una cobertura de más del 90% como bonificación. Use la cobertura de código para resaltar fragmentos de código que se ha perdido (aunque no debería suceder si TDD ... ya que escribe el código solo para pasar una prueba. Ningún código puede existir sin su prueba asociada).

Gishu
fuente
44
- Excepciones: si no prueba su manejo de excepciones, ¿cómo sabe que su código no explota cuando eso sucede? - Setters / Getters: supongo que sensible al contexto, pero seguramente sus pruebas deberían ejecutarlas como parte del conjunto de pruebas, y si no lo están, ¿realmente se están utilizando?
tddmonkey
1
Las excepciones deben ser excepcionales, no se supone que sucedan. Si lo hacen, registra el punto de falla y la fianza. No puede probar todas las excepciones que puedan ocurrir. Si se supone que la aplicación maneja una ruta / evento no feliz, debe hacerse una prueba. Se pueden agregar accesores para futuros clientes ... depende
Gishu
55
No estoy seguro de qué quiere decir con su segundo punto "pero aún he probado todas sus rutas de código". Si de hecho quiere decir cobertura de ruta completa, entonces no, no puede tener cobertura de ruta completa sin una cobertura de línea / rama / decisión del 100%. De hecho, la cobertura de ruta completa generalmente no se puede obtener en ningún programa no trivial debido a la naturaleza combinatoria de las ramas en la generación de rutas. en.wikipedia.org/wiki/Code_coverage#Other_coverage_criteria
Zach Burlingame
3
No prueba todas las excepciones posibles; Por supuesto que no puedes hacer eso. DEBE apuntar a probar cada bloque de código que maneja excepciones. Por ejemplo, si tiene el requisito de que cuando el bloque X arroja una excepción, la excepción se registra en la base de datos, la franja verde en la parte inferior de la pantalla se vuelve roja y se envía un correo electrónico al Papa; entonces eso es lo que debes probar. Pero no tiene que probar todas las posibles excepciones que puedan desencadenar estos eventos.
Dawood ibn Kareem
2
+1 para "Usar cobertura de código para resaltar fragmentos de código que se ha perdido". Eso es básicamente para qué sirve esa métrica.
beluchin
61

La cobertura de código es excelente, pero la cobertura de funcionalidad es aún mejor. No creo en cubrir cada línea que escribo. Pero sí creo en escribir una cobertura de prueba del 100% de toda la funcionalidad que quiero proporcionar (incluso para las características extra interesantes que vine conmigo y que no se discutieron durante las reuniones).

No me importa si tendría un código que no está cubierto en las pruebas, pero me importaría si refactorizara mi código y terminara teniendo un comportamiento diferente. Por lo tanto, el 100% de cobertura funcional es mi único objetivo.

tofi9
fuente
44
Esta es una respuesta fantástica. El código que cumple con sus requisitos es un objetivo mucho más valioso que el código que cumple con alguna métrica de cobertura de LoC arbitraria.
Dawood ibn Kareem
46
Si puede proporcionar toda la funcionalidad sin presionar todas las líneas de código, ¿qué están haciendo esas líneas de código adicionales allí?
Jens Timmerman
44
@JensTimmerman teóricamente tienes razón. Sin embargo, la cobertura del 100% del código es demasiado costosa en el tiempo, y obligar a mi equipo a hacerlo no solo los desmotiva, sino que también hace que mi proyecto se ejecute en la fecha límite. Me gusta estar en algún lugar en el medio, y la funcionalidad de prueba (llámalo: prueba de integración) es con lo que me siento cómodo. ¿Qué código no pruebo? Manejo de excepciones técnicas, (rango / parámetro) verificaciones que podrían ser necesarias. En resumen, toda la plomería técnica que aprendí a aplicar por experiencia propia o las mejores prácticas sobre las que leí.
tofi9
2
Llevé esto un paso más allá al hacer una lista de situaciones comunes que deberían incluirse o excluirse de las pruebas. De esa manera, nunca nos dirigimos hacia un porcentaje, sino más bien una cobertura funcional de todas las partes de la base de código de trabajo.
Skeeterdrums
58

La respuesta aceptada hace un buen punto: no hay un solo número que tenga sentido como estándar para cada proyecto. Hay proyectos que simplemente no necesitan ese estándar. Cuando la respuesta aceptada se queda corta, en mi opinión, es en describir cómo se puede tomar esa decisión para un proyecto dado.

Intentaré hacerlo. No soy un experto en ingeniería de pruebas y me complacería ver una respuesta más informada.

Cuándo establecer los requisitos de cobertura del código

Primero, ¿por qué querrías imponer tal estándar en primer lugar? En general, cuando desea introducir confianza empírica en su proceso. ¿Qué quiero decir con "confianza empírica"? Bueno, la verdadera corrección del objetivo . Para la mayoría del software, no podemos saber esto en todas las entradas, por lo que nos conformamos con decir que el código está bien probado . Esto es más conocido, pero sigue siendo un estándar subjetivo: siempre estará abierto a debatir si lo has cumplido o no. Esos debates son útiles y deberían ocurrir, pero también exponen incertidumbre.

La cobertura del código es una medida objetiva: una vez que vea su informe de cobertura, no hay ambigüedad sobre si los estándares cumplidos son útiles. ¿Prueba lo correcto? En absoluto, pero tiene una relación clara con lo bien probado que está el código, que a su vez es nuestra mejor manera de aumentar la confianza en su corrección. La cobertura del código es una aproximación medible de cualidades inconmensurables que nos interesan.

Algunos casos específicos en los que tener un estándar empírico podría agregar valor:

  • Para satisfacer a los interesados. Para muchos proyectos, hay varios actores interesados ​​en la calidad del software que pueden no estar involucrados en el desarrollo diario del software (gerentes, líderes técnicos, etc.) diciendo "vamos a escribir todos los las pruebas que realmente necesitamos "no son convincentes: necesitan confiar por completo o verificar con una estrecha supervisión continua (suponiendo que incluso tengan el conocimiento técnico para hacerlo). Proporcionar estándares medibles y explicar cómo aproximan razonablemente los objetivos reales es mejor.
  • Para normalizar el comportamiento del equipo. Dejando de lado a las partes interesadas, si está trabajando en un equipo donde varias personas escriben códigos y pruebas, hay espacio para la ambigüedad de lo que califica como "bien probado". ¿Todos sus colegas tienen la misma idea de qué nivel de prueba es lo suficientemente bueno? Probablemente no. ¿Cómo reconcilias esto? Encuentre una métrica en la que todos puedan estar de acuerdo y acéptela como una aproximación razonable. Esto es especialmente útil (pero no exclusivo) en equipos grandes, donde los clientes potenciales pueden no tener supervisión directa sobre los desarrolladores junior, por ejemplo. Las redes de confianza también son importantes, pero sin mediciones objetivas, es fácil que el comportamiento del grupo sea inconsistente, incluso si todos actúan de buena fe.
  • Para mantenerte honesto. Incluso si es el único desarrollador y la única parte interesada en su proyecto, es posible que tenga ciertas cualidades en mente para el software. En lugar de realizar evaluaciones subjetivas continuas sobre qué tan bien probado está el software (lo que requiere trabajo), puede usar la cobertura del código como una aproximación razonable y dejar que las máquinas lo midan por usted.

Qué métricas usar

La cobertura del código no es una sola métrica; Hay varias formas diferentes de medir la cobertura. El criterio sobre el que puede establecer un estándar depende de lo que esté usando para satisfacerlo.

Usaré dos métricas comunes como ejemplos de cuándo podría usarlas para establecer estándares:

  • Cobertura de la declaración : ¿Qué porcentaje de declaraciones se han ejecutado durante las pruebas? Útil para tener una idea de la cobertura física de su código: ¿Cuánto del código que he escrito he probado realmente?
    • Este tipo de cobertura admite un argumento de corrección más débil, pero también es más fácil de lograr. Si solo está utilizando la cobertura de código para garantizar que las cosas se prueben (y no como un indicador de la calidad de la prueba más allá de eso), entonces la cobertura de la declaración es probablemente suficiente.
  • Cobertura de sucursales : cuando existe una lógica de ramificación (por ejemplo, an if), ¿se han evaluado ambas ramas? Esto da una mejor idea de la cobertura lógica de su código: ¿Cuántas de las posibles rutas que puede tomar mi código he probado?
    • Este tipo de cobertura es un indicador mucho mejor de que un programa ha sido probado en un conjunto integral de entradas. Si está utilizando la cobertura de código como su mejor aproximación empírica para la confianza en la corrección, debe establecer estándares basados ​​en la cobertura de sucursal o similar.

Hay muchas otras métricas (la cobertura de línea es similar a la cobertura de declaración, pero produce diferentes resultados numéricos para declaraciones de varias líneas, por ejemplo; la cobertura condicional y la cobertura de ruta es similar a la cobertura de rama, pero reflejan una vista más detallada de las posibles permutaciones de ejecución del programa que pueda encontrar).

Qué porcentaje requerir

Finalmente, volviendo a la pregunta original: si establece estándares de cobertura de código, ¿cuál debería ser ese número?

Esperemos que esté claro en este punto que estamos hablando de una aproximación para comenzar, por lo que cualquier número que elijamos será inherentemente aproximado.

Algunos números que uno podría elegir:

  • 100% . Puede elegir esto porque desea asegurarse de que todo esté probado. Esto no le da una idea de la calidad de la prueba, pero le dice que alguna prueba de cierta calidad ha tocado cada declaración (o rama, etc.) Nuevamente, esto vuelve al grado de confianza: si su cobertura es inferior al 100% , sabes que algún subconjunto de tu código no ha sido probado.
    • Algunos podrían argumentar que esto es una tontería, y solo debe probar las partes de su código que son realmente importantes. Yo diría que también debe mantener solo las partes de su código que son realmente importantes. La cobertura del código puede mejorarse eliminando también el código no probado.
  • 99% (o 95%, otros números en los noventa altos). Apropiado en los casos en que desea transmitir un nivel de confianza similar al 100%, pero dése un margen para no preocuparse por el rincón ocasional difícil de probar. código.
  • 80% . He visto este número en uso varias veces, y no sé del todo dónde se origina. Yo creo que podría ser una apropiación indebida extraña de la regla 80-20; en general, la intención aquí es mostrar que la mayoría se prueba la de su código. (Sí, el 51% también sería "la mayoría", pero el 80% refleja mejor lo que la mayoría de la gente quiere decir con la mayoría). Esto es apropiado para casos intermedios donde "bien probado" no es una alta prioridad (usted no ' no quiere desperdiciar el esfuerzo en pruebas de bajo valor), pero es una prioridad suficiente que aún le gustaría tener algún estándar en su lugar.

No he visto números por debajo del 80% en la práctica, y me cuesta imaginar un caso en el que uno los establezca. El papel de estos estándares es aumentar la confianza en la corrección, y los números por debajo del 80% no son particularmente inspiradores de confianza. (Sí, esto es subjetivo, pero de nuevo, la idea es hacer la elección subjetiva una vez que establezca el estándar y luego usar una medición objetiva en el futuro).

Otras notas

Lo anterior supone que el objetivo es la corrección. La cobertura del código es solo información; Puede ser relevante para otros objetivos. Por ejemplo, si le preocupa la capacidad de mantenimiento, probablemente le interese el acoplamiento suelto, que puede demostrarse mediante la capacidad de prueba, que a su vez se puede medir (en ciertas modas) mediante la cobertura del código. Por lo tanto, su estándar de cobertura de código proporciona una base empírica para aproximar también la calidad de la "mantenibilidad".

mata pantalla
fuente
Buena respuesta. ¿Me pueden ayudar a encontrar cobertura de funcionalidad a través de pruebas unitarias? ¿Alguna herramienta que me puede ayudar a lograr esto?
curlyreggie
2
Gran respuesta. Es el único que se centra en las pruebas como un problema de equipo en un entorno industrial. No puedo revisar todo y mi equipo es muy brillante, pero ecológico. Establecí un porcentaje de piso del 90% en un nuevo proyecto como verificación de cordura para los desarrolladores junior, no porque creo que sea "suficiente". "90%" y "positivo, negativo y nulo" son mantras fáciles para desarrolladores brillantes y jóvenes que sé que harán un buen trabajo, pero no tienen la experiencia para seguir adelante y escribir ese caso de prueba adicional que es molesto Detrás de tu mente.
0x1mason
2
Creo que esta es la mejor respuesta disponible.
bugkiller
27

La cobertura de mi código favorito es 100% con un asterisco. El asterisco aparece porque prefiero usar herramientas que me permitan marcar ciertas líneas como líneas que "no cuentan". Si he cubierto el 100% de las líneas que "cuentan", ya he terminado.

El proceso subyacente es:

  1. Escribo mis pruebas para ejercitar toda la funcionalidad y los casos límite que se me ocurren (generalmente trabajando a partir de la documentación).
  2. Ejecuto las herramientas de cobertura de código
  3. Examino las líneas o rutas no cubiertas y las que considero no importantes o inalcanzables (debido a la programación defensiva) que marco como no contando
  4. Escribo nuevas pruebas para cubrir las líneas faltantes y mejorar la documentación si no se mencionan esos casos extremos.

De esta manera, si yo y mis colaboradores agregamos un nuevo código o cambiamos las pruebas en el futuro, hay una línea brillante que nos dice si nos perdimos algo importante: la cobertura cayó por debajo del 100%. Sin embargo, también proporciona la flexibilidad para lidiar con diferentes prioridades de prueba.

Epónimo
fuente
3
@ErikE Asterix es, por supuesto, un guerrero bajo pero valiente de la Galia que crea excepciones a la monótona ocupación romana y, por lo tanto, el pequeño símbolo tipográfico que marca las excepciones lleva su nombre. (Más en serio, gracias, lo he arreglado la falta de ortografía.)
Eponymous
3
¿Le gustaría incluir las "herramientas que le permiten [marcar] ciertas líneas como líneas que no cuentan"?
domdambrogia
2
@domdambrogia Como ejemplo en PHP, si usa la biblioteca de cobertura de código de Bergmann, anote una línea con // @codeCoverageIgnorey se excluirá de la cobertura.
obispo el
19

Me gustaría compartir otro anectodo sobre la cobertura de prueba.

Tenemos un gran proyecto en el que, en Twitter, noté que, con 700 pruebas unitarias, solo tenemos un 20% de cobertura de código .

Scott Hanselman respondió con palabras de sabiduría :

¿Es el DERECHO del 20%? ¿Es el 20% lo que representa el código que más usan sus usuarios? Puede agregar 50 pruebas más y solo agregar 2%.

Nuevamente, se remonta a mi Testivus en la respuesta de cobertura de código . ¿Cuánto arroz debes poner en la olla? Depende.

Jon Limjap
fuente
Obviamente tiene que haber sentido común allí. No sirve de mucho si el 50% del código que está probando son comentarios.
cordura
2
Está más en la línea de ... ¿su cobertura se gasta en la funcionalidad principal de su aplicación, o está probando inútilmente funciones triviales / agradables?
Jon Limjap
parece que un gran porcentaje de su código es repetitivo, o manejo de excepciones, o cosas condicionales de "modo de depuración"
Erik Aronesty
8

Para un sistema bien diseñado, donde las pruebas unitarias han impulsado el desarrollo desde el principio, diría que el 85% es un número bastante bajo. Las clases pequeñas diseñadas para ser comprobables no deberían ser difíciles de cubrir mejor que eso.

Es fácil descartar esta pregunta con algo como:

  • Las líneas cubiertas no son iguales a la lógica probada y no se debe leer demasiado en el porcentaje.

Es cierto, pero hay algunos puntos importantes que hacer sobre la cobertura del código. En mi experiencia, esta métrica es bastante útil cuando se usa correctamente. Dicho esto, no he visto todos los sistemas y estoy seguro de que hay toneladas de ellos en los que es difícil ver el análisis de cobertura de código que agrega algún valor real. El código puede verse muy diferente y el alcance del marco de prueba disponible puede variar.

Además, mi razonamiento se refiere principalmente a bucles de retroalimentación de prueba bastante cortos. Para el producto que estoy desarrollando, el ciclo de retroalimentación más corto es bastante flexible y abarca desde pruebas de clase hasta señalización entre procesos. Por lo general, probar un subproducto entregable lleva 5 minutos y, para un ciclo de retroalimentación tan corto, de hecho es posible usar los resultados de la prueba (y específicamente la métrica de cobertura de código que estamos viendo aquí) para rechazar o aceptar confirmaciones en el repositorio.

Al usar la métrica de cobertura del código, no solo debe tener un porcentaje fijo (arbitrario) que debe cumplirse. Hacer esto no le brinda los beneficios reales del análisis de cobertura de código en mi opinión. En su lugar, defina las siguientes métricas:

  • Low Water Mark (LWM), el número más bajo de líneas descubiertas jamás visto en el sistema bajo prueba
  • High Water Mark (HWM), el porcentaje de cobertura de código más alto jamás visto para el sistema bajo prueba

El nuevo código solo se puede agregar si no vamos por encima del LWM y no vamos por debajo del HWM. En otras palabras, no se permite que disminuya la cobertura del código , y se debe cubrir el nuevo código. Observe cómo digo debería y no debe (explicado a continuación).

Pero, ¿no significa esto que será imposible limpiar la basura vieja y bien probada para la que ya no tiene uso? Sí, y es por eso que debes ser pragmático sobre estas cosas. Hay situaciones en las que las reglas tienen que romperse, pero para su integración diaria típica, mi experiencia es que estas métricas son bastante útiles. Dan las siguientes dos implicaciones.

  • Se promueve el código comprobable. Al agregar un nuevo código, realmente debe hacer un esfuerzo para que el código sea comprobable, ya que tendrá que intentar cubrirlo todo con sus casos de prueba. El código comprobable suele ser algo bueno.

  • La cobertura de prueba para el código heredado aumenta con el tiempo. Al agregar un nuevo código y no poder cubrirlo con un caso de prueba, se puede tratar de cubrir algún código heredado para evitar la regla LWM. Esta trampa a veces necesaria al menos da el efecto secundario positivo de que la cobertura del código heredado aumentará con el tiempo, haciendo que la aplicación aparentemente estricta de estas reglas sea bastante pragmática en la práctica.

Y de nuevo, si el ciclo de retroalimentación es demasiado largo, puede ser completamente poco práctico configurar algo como esto en el proceso de integración.

También me gustaría mencionar dos beneficios generales más de la métrica de cobertura del código.

  • El análisis de cobertura de código es parte del análisis de código dinámico (en oposición al análisis estático, es decir, Lint). Los problemas encontrados durante el análisis de código dinámico (por herramientas como la familia purify, http://www-03.ibm.com/software/products/en/rational-purify-family ) son cosas como lecturas de memoria no inicializadas (UMR), pérdidas de memoria, etc. Estos problemas solo se pueden encontrar si el código está cubierto por un caso de prueba ejecutado . El código que es más difícil de cubrir en un caso de prueba suele ser los casos anormales en el sistema, pero si desea que el sistema falle correctamente (es decir, el seguimiento de errores en lugar de bloquearse) es posible que desee esforzarse para cubrir los casos anormales en el análisis de código dinámico también. Con solo un poco de mala suerte, un UMR puede conducir a una falla por defecto o peor.

  • Las personas se enorgullecen de mantener el 100% para el nuevo código, y discuten los problemas de prueba con una pasión similar a otros problemas de implementación. ¿Cómo se puede escribir esta función de una manera más comprobable? ¿Cómo tratarías de cubrir este caso anormal, etc.

Y una negativa, para completar.

  • En un proyecto grande con muchos desarrolladores involucrados, no todos serán genios de las pruebas con seguridad. Algunas personas tienden a usar la métrica de cobertura del código como prueba de que el código está probado y esto está muy lejos de la verdad , como se menciona en muchas de las otras respuestas a esta pregunta. Es UNA métrica que puede brindarle algunos beneficios agradables si se usa correctamente, pero si se usa incorrectamente, puede conducir a malas pruebas. Además de los efectos secundarios muy valiosos mencionados anteriormente, una línea cubierta solo muestra que el sistema bajo prueba puede alcanzar esa línea para algunos datos de entrada y que puede ejecutarse sin colgarse o bloquearse.
Martin G
fuente
7

Si este fuera un mundo perfecto, el 100% del código estaría cubierto por pruebas unitarias. Sin embargo, dado que este NO es un mundo perfecto, es una cuestión de para qué tienes tiempo. Como resultado, recomiendo centrarse menos en un porcentaje específico y centrarse más en las áreas críticas. Si su código está bien escrito (o al menos un facsímil razonable del mismo) debe haber varios puntos clave donde las API están expuestas a otro código.

Concentre sus esfuerzos de prueba en estas API. Asegúrese de que las API estén 1) bien documentadas y 2) tengan escritos los casos de prueba que coincidan con la documentación. Si los resultados esperados no coinciden con los documentos, entonces tiene un error en su código, documentación o casos de prueba. Todos los cuales son buenos para examinar.

¡Buena suerte!

64BitBob
fuente
6

Muchas tiendas no valoran las pruebas, por lo que si está por encima de cero, al menos, hay una apreciación del valor, por lo que podría decirse que no es cero, ya que muchas siguen siendo cero.

En el mundo .Net, la gente suele citar el 80% como razonable. Pero dicen esto a nivel de solución. Prefiero medir a nivel de proyecto: el 30% podría estar bien para el proyecto de interfaz de usuario si tiene Selenium, etc. o pruebas manuales, el 20% para el proyecto de capa de datos podría estar bien, pero el 95% o más podría ser bastante alcanzable para el negocio capa de reglas, si no es totalmente necesaria. Por lo tanto, la cobertura general puede ser, digamos, del 60%, pero la lógica comercial crítica puede ser mucho mayor.

También he escuchado esto: aspira al 100% y llegarás al 80%; pero aspira al 80% y alcanzarás el 40%.

En pocas palabras: aplique la regla 80:20 y deje que el recuento de errores de su aplicación lo guíe.

Greg Trevellick
fuente
4

El 85% sería un buen punto de partida para los criterios de registro.

Probablemente elegí una variedad de barras más altas para los criterios de envío, dependiendo de la importancia de los subsistemas / componentes que se prueban.

stephbu
fuente
54
¿Cómo llegaste a ese porcentaje?
cordura
Como nota al pie, esto puede ser complicado para proyectos donde la automatización es difícil, ya que siempre se pragmático sobre lo que se puede lograr frente a lo deseable.
stephbu
44
Principalmente a través de la experimentación. Es bastante fácil llegar a una cobertura de código del 80-90% para las pruebas unitarias relacionadas con Dev, ir más alto normalmente requiere una intervención de prueba divina o rutas de código realmente simples.
stephbu
1
Comienzo generalmente con 1) rutas principales de código de tiempo de ejecución 2) casos obvios de excepción que arrojo explícitamente 3) casos condicionales que terminan con "falla" Esto generalmente lo lleva al rango de 70-80 Luego wackamole, errores y regresiones para casos de esquina, parámetro fuzzing, etc. Refactorización para permitir la inyección de métodos, etc. Generalmente, al menos tengo el mismo tiempo para escribir / refactorizar pruebas relacionadas con el desarrollo que el código principal.
stephbu
4

Utilizo cobertura, y sea cual sea el porcentaje, recomendaría mantener actualizados los valores de la tarea de verificación de cobertura. Como mínimo, siga aumentando la alineación total y la ramificación total por debajo de su cobertura actual, pero nunca baje esos valores. También vincule la propiedad de falla de compilación Ant a esta tarea. Si la compilación falla por falta de cobertura, conoce el código agregado de alguien pero no lo ha probado. Ejemplo:

<cobertura-check linerate="0"
                 branchrate="0"
                 totallinerate="70"
                 totalbranchrate="90"
                 failureproperty="build.failed" />
Gary Kephart
fuente
4

Cuando creo que mi código no se ha probado lo suficiente en la unidad y no estoy seguro de qué probar a continuación, utilizo la cobertura para ayudarme a decidir qué probar a continuación.

Si aumento la cobertura en una prueba unitaria, sé que esta prueba unitaria vale algo.

Esto va para el código que no está cubierto, 50% cubierto o 97% cubierto.

albañil
fuente
3
No estoy de acuerdo por completo. Una prueba unitaria solo vale algo si existe la posibilidad de que descubra un error (ya sea un error que existe ahora o un error de regresión en el futuro); o si ayuda a documentar el comportamiento de su clase. Si un método es tan simple que realmente no puede fallar, como un captador de una línea, entonces hay un valor cero al proporcionarle una prueba unitaria.
Dawood ibn Kareem
66
Tuve errores en los captadores de una línea. Desde mi experiencia, no hay código libre de errores. No hay ningún método que realmente no pueda fallar.
brickner
1
Suponiendo que su getter de una línea es utilizado por otro código que cubre, y las pruebas de ese código pasan, entonces también ha cubierto indirectamente el getter de una línea. Si no está utilizando el getter, ¿qué está haciendo en su código? Estoy de acuerdo con David Wallace ... no hay necesidad de probar directamente las funciones de ayuda simples que se usan en otros lugares si el código y las pruebas que dependen del ayudante no muestran que pueda haber un problema con él.
Lowell Montgomery
@LowellMontgomery y ¿qué pasa si la prueba para su otro código falla debido a ese getter de una línea (que no se probó)? Si hubiera una prueba en el lugar para el one-liner, sería mucho más fácil llegar a la causa de la falla. Se pone realmente mal cuando tienes cientos de líneas simples no probadas que se usan en varios lugares diferentes.
Daniel
La suposición fue que las pruebas con el getter de una línea pasaron. Si falla (por ejemplo, cuando intenta utilizar el valor de retorno de su captador de una línea), puede solucionarlo. Pero a menos que haya una razón realmente apremiante para ser tan paranoico, debes trazar la línea en alguna parte. Mi experiencia ha sido que necesito priorizar lo que me quita el tiempo y la atención y los "captadores" realmente simples (que funcionan) no necesitan pruebas separadas. Se puede dedicar ese tiempo a mejorar otras pruebas o a obtener una cobertura más completa del código que es más probable que falle. (es decir, mantengo mi posición original, con David Wallace).
Lowell Montgomery
4

Prefiero hacer BDD, que utiliza una combinación de pruebas de aceptación automatizadas, posiblemente otras pruebas de integración y pruebas unitarias. La pregunta para mí es cuál debería ser la cobertura objetivo del conjunto de pruebas automatizadas en su conjunto.

Aparte de eso, la respuesta depende de su metodología, idioma y herramientas de prueba y cobertura. Al hacer TDD en Ruby o Python no es difícil mantener una cobertura del 100%, y vale la pena hacerlo. Es mucho más fácil administrar una cobertura del 100% que una cobertura del 90%.Es decir, es mucho más fácil llenar los vacíos de cobertura a medida que aparecen (y cuando se hacen brechas de cobertura de TDD son raros y generalmente valen la pena) que administrar una lista de vacíos de cobertura a los que no ha llegado y perder la cobertura regresiones debido a su fondo constante de código descubierto.

La respuesta también depende de la historia de su proyecto. Solo he encontrado que lo anterior es práctico en proyectos gestionados de esa manera desde el principio. He mejorado enormemente la cobertura de grandes proyectos heredados, y valió la pena hacerlo, pero nunca me pareció práctico volver y llenar cada vacío de cobertura, porque el código antiguo no probado no se entiende lo suficiente como para hacerlo correctamente y con rapidez.

Dave Schweisguth
fuente
3

Si ha estado haciendo pruebas unitarias durante un período de tiempo decente, no veo ninguna razón para que no se acerque al 95% o más. Sin embargo, como mínimo, siempre he trabajado con el 80%, incluso cuando soy nuevo en las pruebas.

Este número solo debe incluir el código escrito en el proyecto (excluye marcos, complementos, etc.) e incluso puede excluir ciertas clases compuestas completamente de código escrito de llamadas a código externo. Este tipo de llamada debe ser burlada / apagada.

Tony Pitale
fuente
3

En términos generales, de los varios documentos de mejores prácticas de excelencia en ingeniería que he leído, el 80% para el nuevo código en las pruebas unitarias es el punto que produce el mejor rendimiento. Superar ese CC% produce una menor cantidad de defectos por la cantidad de esfuerzo ejercido. Esta es una práctica recomendada que utilizan muchas grandes corporaciones.

Desafortunadamente, la mayoría de estos resultados son internos de las empresas, por lo que no hay literatura pública a la que pueda señalarle.

usuario17222
fuente
3

La cobertura del código es excelente, pero solo mientras los beneficios que obtenga superen el costo / esfuerzo de lograrlo.

Hemos estado trabajando con un estándar del 80% durante algún tiempo, sin embargo, acabamos de tomar la decisión de abandonar esto y, en cambio, centrarnos más en nuestras pruebas. Concentrándose en la compleja lógica de negocios, etc.

Esta decisión se tomó debido a la creciente cantidad de tiempo que pasamos persiguiendo la cobertura del código y manteniendo las pruebas unitarias existentes. Sentimos que habíamos llegado al punto en que el beneficio que estábamos obteniendo de nuestra cobertura de código se consideraba menor que el esfuerzo que tuvimos que hacer para lograrlo.

Simon Keep
fuente
2

Respuesta corta: 60-80%

Respuesta larga: creo que depende totalmente de la naturaleza de su proyecto. Normalmente comienzo un proyecto por unidad probando cada pieza práctica. En el primer "lanzamiento" del proyecto, debería tener un porcentaje base bastante bueno basado en el tipo de programación que está realizando. En ese punto, puede comenzar a "aplicar" una cobertura mínima de código.

usuario11087
fuente
2

Echa un vistazo a Crap4j . Es un enfoque un poco más sofisticado que la cobertura de código directo. Combina medidas de cobertura de código con medidas de complejidad, y luego le muestra qué código complejo no se prueba actualmente.

Don Kirkby
fuente
2

Mi respuesta a este enigma es tener una cobertura de línea del 100% del código que puede probar y una cobertura de línea del 0% del código que no puede probar.

Mi práctica actual en Python es dividir mis módulos .py en dos carpetas: app1 / y app2 / y al ejecutar pruebas unitarias calcule la cobertura de esas dos carpetas y verifique visualmente ( debo automatizar esto algún día) que app1 tiene una cobertura del 100% y app2 tiene 0% de cobertura.

Cuando / si encuentro que estos números difieren del estándar que investigo y alteran el diseño del código para que la cobertura se ajuste al estándar.

Esto significa que puedo recomendar lograr una cobertura de línea del 100% del código de la biblioteca.

También ocasionalmente reviso la aplicación2 / para ver si puedo probar algún código allí, y si puedo moverlo a la aplicación1 /

Ahora no estoy demasiado preocupado por la cobertura agregada porque puede variar enormemente dependiendo del tamaño del proyecto, pero en general he visto del 70% a más del 90%.

Con Python, debería ser capaz de diseñar una prueba de humo que pueda ejecutar automáticamente mi aplicación mientras se mide la cobertura y, con suerte, obtener un agregado del 100% al combinar la prueba de humo con las cifras de prueba de unidad.

quamrana
fuente
2

Ver la cobertura desde otra perspectiva: el código bien escrito con un flujo claro de control es el más fácil de cubrir, el más fácil de leer y, por lo general, el código con menos errores. Al escribir código con claridad y capacidad de cobertura en mente, y al escribir las pruebas unitarias en paralelo con el código, obtendrá los mejores resultados en mi humilde opinión.


fuente
2

En mi opinión, la respuesta es "depende de cuánto tiempo tengas". Trato de alcanzar el 100%, pero no hago un escándalo si no lo consigo con el tiempo que tengo.

Cuando escribo pruebas unitarias, uso un sombrero diferente en comparación con el que uso cuando desarrollo el código de producción. Pienso en lo que dice hacer el código probado y cuáles son las situaciones que pueden romperlo.

Normalmente sigo los siguientes criterios o reglas:

  1. Que la Prueba de Unidad debe ser una forma de documentación sobre cuál es el comportamiento esperado de mis códigos, es decir. la salida esperada dada una cierta entrada y las excepciones que puede arrojar que los clientes pueden querer atrapar (¿Qué deben saber los usuarios de mi código?)

  2. Que la Prueba de Unidad debería ayudarme a descubrir las condiciones que tal vez aún no haya pensado. (¿Cómo hacer que mi código sea estable y robusto?)

Si estas dos reglas no producen una cobertura del 100%, que así sea. Pero una vez, tengo tiempo, analizo los bloques y líneas descubiertos y determino si todavía hay casos de prueba sin pruebas unitarias o si el código necesita ser refactorizado para eliminar los códigos innecesarios.

Mark Menchavez
fuente
1

Depende mucho de su aplicación. Por ejemplo, algunas aplicaciones consisten principalmente en código GUI que no se puede probar en la unidad.

Thomas
fuente
55
Probablemente deberías usar Model View Presenter para tu interfaz de usuario si estás en un entorno TDD.
Charles Graham
1

No creo que pueda haber una regla B / W.
El código debe revisarse, con especial atención a los detalles críticos.
Sin embargo, si no se ha probado, ¡tiene un error!

Nescio
fuente
No quiero una regla, solo comentarios sobre cualquier experiencia personal sobre la correlación entre el porcentaje de cobertura de código y la efectividad de la prueba unitaria.
cordura
1

Dependiendo de la criticidad del código, cualquier parte del 75% al ​​85% es una buena regla general. El código de envío definitivamente debe probarse más a fondo que en los servicios públicos, etc.

William Keller
fuente
1

Esto tiene que depender de en qué fase del ciclo de vida de desarrollo de aplicaciones se encuentre.

Si ha estado en desarrollo durante un tiempo y ya tiene un montón de código implementado y ahora se está dando cuenta de que necesita pensar en la cobertura del código, entonces debe verificar su cobertura actual (si existe) y luego usar esa línea de base para establecer hitos cada sprint (o un aumento promedio durante un período de sprints), lo que significa asumir la deuda del código mientras continúa entregando valor al usuario final (al menos en mi experiencia, al usuario final no le importa un poco si ha aumentado la prueba cobertura si no ven nuevas funciones).

Dependiendo de su dominio, no es irrazonable disparar al 95%, pero debo decir que, en promedio, verá un caso promedio de 85% a 90%.

codeLes
fuente
1

Creo que el mejor síntoma de la cobertura correcta del código es que la cantidad de problemas concretos que las pruebas unitarias ayudan a solucionar corresponde razonablemente al tamaño del código de pruebas unitarias que creó.

dimarzionista
fuente
1

Creo que lo más importante es saber cuál es la tendencia de la cobertura a lo largo del tiempo y comprender los motivos de los cambios en la tendencia. Si ve los cambios en la tendencia como buenos o malos dependerá de su análisis de la razón.

Rob Scott
fuente
0

Nos dirigíamos a> 80% hasta hace unos días, pero después de que usamos una gran cantidad de código generado, no nos importa el% de edad, sino que hacemos que el revisor atienda la cobertura requerida.

reva
fuente
0

De la publicación de Testivus, creo que el contexto de respuesta debería ser el segundo programador. Dicho esto desde un punto de vista práctico, necesitamos parámetros / objetivos por los que luchar. Considero que esto se puede "probar" en un proceso ágil mediante el análisis del código que tenemos la arquitectura, la funcionalidad (historias de usuarios), y luego obtener un número. Según mi experiencia en el área de telecomunicaciones, diría que el 60% es un buen valor para verificar.

D Lovece
fuente