Ahora sé que la gente podría considerar esta pregunta duplicada o formulada muchas veces, en cuyo caso agradecería un enlace a preguntas relevantes con respuesta a mi pregunta.
Recientemente he estado en desacuerdo con algunas personas sobre la cobertura del código. Tengo un grupo de personas que quieren que nuestro equipo deje de mirar la cobertura del código por completo basándose en el argumento de que una cobertura del 100% no significa pruebas de buena calidad y, por lo tanto, un código de buena calidad.
He podido retroceder al vender el argumento de que Code Coverage me dice lo que no se ha probado con seguridad y nos ayuda a centrarnos en esas áreas.
(Lo anterior se ha discutido de manera similar en otras preguntas SO como esta: /programming/695811/pitfalls-of-code-coverage )
El argumento de estas personas es: entonces el equipo reaccionaría creando rápidamente pruebas de baja calidad y, por lo tanto, perdería tiempo sin agregar una calidad significativa.
Si bien entiendo su punto de vista, estoy buscando una manera de hacer un caso más sólido para la cobertura de código mediante la introducción de herramientas / marcos más robustos que cuiden más criterios de cobertura (Functional, Statement,Decision, Branch, Condition, State, LCSAJ, path, jump path, entry/exit, Loop, Parameter Value etc)
.
Lo que estoy buscando es una sugerencia para una combinación de tales herramientas de cobertura de código y prácticas / procesos para acompañarlos, lo que puede ayudarme a contrarrestar tales argumentos mientras me siento cómodo con mi recomendación.
También agradecería cualquier comentario / sugerencia que lo acompañe basado en su experiencia / conocimiento sobre cómo contrarrestar tal argumento, porque si bien es subjetivo, la cobertura del código ha ayudado a mi equipo a ser más consciente de la calidad del código y el valor de las pruebas.
Editar: para reducir cualquier confusión sobre mi comprensión de la debilidad de la cobertura de código típica, quiero señalar que no me estoy refiriendo a Statement Coverage
(o líneas de código ejecutadas) herramientas (hay muchas). De hecho, aquí hay un buen artículo sobre todo lo que tiene de malo: http://www.bullseye.com/statementCoverage.html
Estaba buscando algo más que una declaración o cobertura de línea, yendo más a múltiples criterios y niveles de cobertura.
Ver: http://en.wikipedia.org/wiki/Code_coverage#Coverage_criteria
La idea es que si una herramienta nos puede decir nuestra cobertura basada en múltiples criterios, entonces eso se convierte en una evaluación automatizada razonable de la calidad de la prueba. De ninguna manera estoy tratando de decir que la cobertura de línea es una buena evaluación. De hecho, esa es la premisa de mi pregunta.
Editar:
Ok, tal vez lo proyecté demasiado dramáticamente, pero entiendes el punto. El problema es establecer procesos / políticas en general en todos los equipos de manera homogénea / consistente. Y el temor es general de que cómo se garantiza la calidad de las pruebas, cómo se asigna el tiempo garantizado sin tener ninguna medida. Por lo tanto, me gusta tener una característica medible que, cuando se respalda con los procesos adecuados y las herramientas adecuadas, nos permitiría mejorar la calidad del código al tiempo que sabemos que el tiempo no se gasta en procesos innecesarios.
EDITAR: hasta ahora lo que tengo de las respuestas:
- Las revisiones del código deben cubrir las pruebas para garantizar la calidad de las pruebas.
- La estrategia Test First ayuda a evitar las pruebas escritas después del hecho para simplemente aumentar el porcentaje de cobertura
- Explorar herramientas alternativas que cubren criterios de prueba que no sean simplemente Declaración / Línea
- El análisis del código cubierto / número de errores encontrados ayudaría a apreciar la importancia de la cobertura y a hacer un mejor caso
- Lo más importante es confiar en la aportación del equipo para hacer lo correcto y luchar por sus creencias.
- Bloques cubiertos / # de pruebas: debatible pero tiene cierto valor
Gracias por las increíbles respuestas hasta ahora. Realmente los aprecio. Este hilo es mejor que horas de lluvia de ideas con los poderes fácticos.
fuente
Respuestas:
En mi experiencia, la cobertura del código es tan útil como la crea . Si escribe buenas pruebas que cubren todos sus casos, entonces pasar esas pruebas significa que ha cumplido con sus requisitos. De hecho, esa es la idea exacta que utiliza Test Driven Development . Escribe las pruebas antes del código sin saber nada sobre la implementación (a veces esto significa que otro equipo escribe las pruebas por completo). Estas pruebas se configuran para verificar que el producto final hace todo lo que sus especificaciones dicen que hizo, y LUEGO escribe el código mínimo para pasar esas pruebas.
El problema aquí, obviamente, es que si sus pruebas no son lo suficientemente fuertes, perderá casos extremos o problemas imprevistos y escribirá código que realmente no cumple con sus especificaciones. Si realmente está decidido a usar pruebas para verificar su código, escribir buenas pruebas es una necesidad absoluta, o realmente está perdiendo el tiempo.
Quería editar la respuesta aquí porque me di cuenta de que realmente no respondía a su pregunta. Vería ese artículo wiki para ver algunos beneficios declarados de TDD. Realmente se trata de cómo funciona mejor su organización, pero TDD es definitivamente algo en uso en la industria.
fuente
Statement Coverage
(o líneas de código ejecutadas). Estaba buscando algo más que una declaración o cobertura de línea, profundizandomultiple coverage criteria
y nivelando. Ver: en.wikipedia.org/wiki/Code_coverage#Coverage_criteria y en.wikipedia.org/wiki/Linear_Code_Sequence_and_Jump . La idea es que si una herramienta nos puede decir nuestra cobertura basada en múltiples criterios, entonces eso se convierte en una evaluación automatizada razonable de la calidad de la prueba. De ninguna manera estoy tratando de decir que la cobertura de línea es una buena evaluación. De hecho, esa es la premisa de mi pregunta.En primer lugar, las personas hacen defensor de cobertura del 100%:
Steve McConnell, Code Complete , Capítulo 22: Pruebas de desarrollador.
Como usted y otros han mencionado, es poco probable que la cobertura de código solo por el bien de la cobertura logre mucho. Pero si no puede ejecutar una línea de código, ¿por qué está escrita?
Sugeriría resolver el argumento reuniendo y analizando datos en sus propios proyectos.
Para recopilar los datos, personalmente uso las siguientes herramientas:
Una vez que tenga eso (o algo similar) en su lugar, puede comenzar a mirar sus propios datos más de cerca:
Yo esperaría que sus datos van a apoyar su posición sobre la cobertura de código; esa ciertamente ha sido mi experiencia. Sin embargo, si no es así, tal vez su organización pueda tener éxito con estándares de cobertura de código más bajos de lo que quisiera. O tal vez tus pruebas no son muy buenas. Con suerte, la tarea centrará el esfuerzo en producir software con menos defectos, independientemente de la resolución del desacuerdo de cobertura del código.
fuente
Este es un problema de confianza , no de herramientas .
Pregúnteles por qué, si realmente creen esa afirmación, ¿confiarían en que el equipo escriba algún código?
fuente
Creo que ese es el problema. Los desarrolladores no se preocupan (y a menudo por excelentes razones) sobre políticas consistentes o globales, y desean la libertad de hacer lo que piensan que es correcto en lugar de cumplir con las políticas corporativas.
Lo cual es razonable a menos que demuestre que los procesos y medidas globales tienen valor y un efecto positivo en la calidad y la velocidad de desarrollo.
Cronología habitual:
fuente
En mi experiencia, hay algunas cosas para combinar con la cobertura de código para que la métrica valga la pena:
Revisiones de código
Si puede devolver las pruebas negativas al desarrollador, puede ayudar a limitar la cantidad de pruebas incorrectas que proporcionan esta cobertura sin sentido.
Seguimiento de errores
Si tiene un montón de cobertura de código en un módulo, pero aún tiene muchos errores graves en esa área, podría indicar un problema en el que ese desarrollador necesita mejorar con sus pruebas.
Pragmatismo
Nadie va a llegar al 100% con buenas pruebas en código no trivial. Si usted como líder del equipo, observe la cobertura del código, pero en lugar de decir "¡necesitamos llegar al N%!" identifica las brechas y pide a las personas que "mejoren la cobertura en el módulo X" que logra su objetivo sin brindarles a las personas la oportunidad de jugar con el sistema.
Bloques cubiertos / # de pruebas
La mayoría de las herramientas de cobertura de código enumeran los bloques cubiertos frente a los bloques no cubiertos. La combinación de esto con el número de pruebas reales le permite obtener una métrica que indica qué tan "amplias" son las pruebas, ya sea indicando malas pruebas o diseño acoplado. Esto es más útil como un delta de un sprint a otro, pero la idea es la misma: combinar la cobertura del código con otras métricas para obtener más información.
fuente
Aquí están mis 2 centavos.
Hay muchas prácticas que han recibido mucha atención recientemente porque pueden aportar beneficios al desarrollo de software. Sin embargo, algunos desarrolladores aplican esas prácticas a ciegas: están convencidos de que aplicar una metodología es como ejecutar un algoritmo y que después de realizar los pasos correctos, se debe obtener el resultado deseado.
Algunos ejemplos:
Creo que el problema básico con las declaraciones anteriores es que los humanos no son computadoras y escribir software no es como ejecutar un algoritmo.
Entonces, las declaraciones anteriores contienen algo de verdad pero simplifican demasiado las cosas, por ejemplo:
Volviendo a la cobertura del código.
Creo que debe juzgar caso por caso si vale la pena tener una cobertura del 100% para un determinado módulo.
¿El módulo realiza algunos cálculos muy importantes y complicados? Luego me gustaría probar cada línea de código, pero también escribir pruebas unitarias significativas (pruebas unitarias que tengan sentido en ese dominio).
¿El módulo realiza alguna tarea importante pero simple como abrir una ventana de ayuda al hacer clic en un botón? Una prueba manual probablemente será más efectiva.
En mi opinión, tienen razón: no puede exigir la calidad del código al solo requerir una cobertura del 100% del código. Agregar más herramientas para calcular la cobertura y hacer estadísticas tampoco ayudará. Por el contrario, debe analizar qué partes del código son más sensibles y deben probarse exhaustivamente y cuáles son menos propensas a errores (en el sentido de que un error puede descubrirse y repararse mucho más fácilmente sin usar pruebas unitarias).
Si aplica una cobertura de código del 100% a los desarrolladores, algunos comenzarán a escribir pruebas unitarias tontas para cumplir con sus obligaciones en lugar de intentar escribir pruebas sensatas.
Tal vez sea una ilusión que puedas medir la inteligencia y el juicio humanos. Si tiene colegas competentes y confía en su criterio, puede aceptar cuando le digan "para este módulo, aumentar la cobertura del código traerá muy pocos beneficios. Por lo tanto, no pasemos tiempo en él" o "para este módulo necesitamos tanta cobertura como podamos obtener, necesitamos una semana extra para implementar pruebas unitarias sensatas ".
Entonces (nuevamente, estos son mis 2 centavos): no intente encontrar un proceso y establezca parámetros como la cobertura de código que debe ajustarse a todos los equipos, para todos los proyectos y para todos los módulos. Encontrar un proceso tan general es una ilusión y creo que cuando haya encontrado uno, será subóptimo.
fuente
"el equipo reaccionaría creando rápidamente pruebas de baja calidad y, por lo tanto, perdería tiempo sin agregar una calidad significativa"
Este es un riesgo real, no solo teórico.
El exceso de código solo es una métrica disfuncional. Aprendí esa lección de la manera difícil. Una vez, lo enfaticé sin la disponibilidad de balancear métricas o prácticas. Cientos de pruebas que capturan y enmascaran excepciones, y sin afirmaciones es algo feo.
"sugerencia para una combinación de tales herramientas de cobertura de código y prácticas / procesos para acompañarlos"
Además de todas las otras sugerencias, existe una técnica de automatización que puede evaluar la calidad de las pruebas: pruebas de mutación ( http://en.wikipedia.org/wiki/Mutation_testing ). Para el código Java, PIT ( http://pitest.org/ ) funciona, y es la primera herramienta de prueba de mutaciones que encuentro.
Como observa, la falta de cobertura de código es fácilmente identificable como un riesgo de calidad de software. Enseño que la cobertura del código es una condición necesaria, pero insuficiente, para la calidad del software. Tenemos que adoptar un enfoque de cuadro de mando integral para gestionar la calidad del software.
fuente
La cobertura del código ciertamente no es prueba de buenas pruebas unitarias, ya que son correctas.
Pero a menos que puedan proporcionar una forma de demostrar que todas las pruebas unitarias son buenas (para cualquier definición de bien que puedan encontrar), este es realmente un punto mudo.
fuente
Siempre he encontrado que la cobertura del código es fácilmente susceptible al efecto Hawthorne . Esto me hizo preguntar "¿por qué tenemos alguna métrica de software?" y la respuesta generalmente es proporcionar una comprensión de alto nivel del estado actual del proyecto, cosas como:
"¿Qué tan cerca estamos de hacer?"
"¿Cómo es la calidad de este sistema?"
"¿Qué tan complicados son estos módulos?"
Por desgracia, nunca habrá una sola métrica que pueda decirle qué tan bueno o malo es el proyecto, y cualquier intento de derivar ese significado de un solo número necesariamente se simplificará demasiado. Si bien las métricas tienen que ver con los datos, interpretar lo que significan es una tarea mucho más emocional / psicológica y, como tal, probablemente no se pueda aplicar genéricamente a equipos de diferentes composiciones o problemas de diferentes dominios.
En el caso de la cobertura, creo que a menudo se usa como un proxy para la calidad del código, aunque sea burdo. Y el verdadero problema es que reduce un tema terriblemente complicado a un solo número entero entre 0 y 100 que, por supuesto, se utilizará para impulsar un trabajo potencialmente inútil en una búsqueda interminable para lograr una cobertura del 100%. Gente como Bob Martin dirá que el 100% de cobertura es el único objetivo serio, y puedo entender por qué es así, porque cualquier otra cosa parece arbitraria.
Por supuesto, hay muchas maneras de obtener cobertura que en realidad no me ayudan a comprender el código base, por ejemplo, ¿es valioso probar toString ()? ¿Qué pasa con getters y setters para objetos inmutables? Un equipo solo tiene mucho esfuerzo para aplicar en un tiempo fijo y ese tiempo siempre parece ser menor que el tiempo requerido para hacer un trabajo perfecto, por lo que en ausencia de un horario perfecto tenemos que conformarnos con aproximaciones.
Una medida que he encontrado útil para hacer buenas aproximaciones es Crap4J . Ahora está desactivado, pero puede portarlo / implementarlo usted mismo fácilmente. Crap4J trata de relacionar la cobertura del código con la complejidad ciclomática al implicar que el código que es más complicado (ifs, whiles, fors, etc.) debería tener una mayor cobertura de prueba. Para mí, esta simple idea realmente sonaba verdadera. Quiero entender dónde hay riesgo en mi base de código, y un riesgo realmente importante es la complejidad. Entonces, usando esta herramienta, puedo evaluar rápidamente cuán riesgoso es mi código base. Si es complicado, es mejor que la cobertura aumente. Si no es así, no necesito perder el tiempo tratando de cubrir cada línea de código.
Por supuesto, esto es solo una métrica y YMMV. Tiene que pasar tiempo con él para comprender si tendrá sentido para usted y si le dará a su equipo una sensación razonablemente acertada de dónde se encuentra el proyecto.
fuente
No diría que regresar y cubrir el código existente es la mejor ruta hacia adelante. Yo diría que tiene sentido escribir pruebas de cobertura para cualquier código nuevo que escriba o cualquier código que cambie.
Cuando se encuentran errores, escriba una prueba que falle debido a ese error y corríjala para que la prueba se vuelva verde. Ponga en los comentarios de la prueba para qué error está escrito.
El objetivo es tener suficiente confianza en sus pruebas para poder hacer cambios sin preocuparse por los efectos secundarios inesperados. Consulte Trabajar eficazmente con código heredado para obtener un buen resumen de los enfoques para domesticar código no probado.
fuente