No debe aplicar la cobertura del código automáticamente.
Esto es como imponer las líneas máximas de código por método: de acuerdo, la mayoría de los métodos deberían ser inferiores a, digamos, 20 LOC, pero hay casos válidos en los que los métodos serían más largos que eso.
De la misma manera, apuntar a un porcentaje dado de cobertura de código por clase puede conducir a consecuencias no deseadas. Por ejemplo:
Las clases de código repetitivo o las clases creadas por generadores de código pueden no probarse en absoluto. Obligar a los desarrolladores a probarlos no tendrá ningún beneficio y tendrá un costo sustancial en términos de tiempo dedicado a hacerlo.
El código simple que maneja partes no importantes de la aplicación no necesariamente tiene que ser probado.
En algunos idiomas, algunos códigos no se pueden probar. Tuve este caso en C # con métodos anónimos en una biblioteca donde realmente quería tener una cobertura de código del 100%. Esos casos pueden ser desmoralizantes para los desarrolladores.
Más importante aún, la cobertura del código debe ser proporcional a dos aspectos del código: cuán crítico y cuán complicado es :
Una pieza de código con una lógica complicada, que es parte de la característica principal de una aplicación, debería probarse cuidadosamente, ya que las fallas o regresiones pueden tener consecuencias importantes.
Un código simple que maneja una característica que nadie usa puede tener pruebas básicas que cubren solo casos básicos.
Por supuesto, aún puede usar la cobertura del código como medida , especialmente para comparar cómo los diferentes equipos logran la cobertura del código: puede haber equipos que sean menos disciplinados y más reacios a la hora de realizar las pruebas. En esos casos, es posible que desee combinar esta métrica con otras, como la cantidad de errores, el tiempo dedicado a resolver errores o la cantidad de comentarios durante las revisiones de código.
También es posible que desee aplicar al menos algo de cobertura de código, digamos 60% ¹, en proyectos individuales donde tenga sentido (tenga cuidado de excluir prototipos, código generado, CRUD, etc.) Haciendo posible que los desarrolladores marquen clases específicas como excluidas desde la cobertura del código también es agradable². En este caso, esto puede hacerse bajo una forma de verificación que falla una compilación si la cobertura del código está por debajo del mínimo requerido. Lo haría en la etapa de compilación, no en la etapa de confirmación , ya que no se espera que ejecute pruebas unitarias durante la confirmación .
¹ Consideraría el 60% como un mínimo razonable basado en mi base de código: casi todos los proyectos o clases que tienen menos del 60% de cobertura de código realmente no han sido probados . Esto puede variar mucho de un idioma a otro y de una compañía a otra (en algunas compañías, el 0% es un estándar). Asegúrese de discutir con su equipo qué es normal y qué es demasiado alto para ellos. Tal vez están constantemente alcanzando el 95% y pueden apuntar fácilmente al 99%, o tal vez luchan por aumentar su cobertura de código del 70% al 75%.
² Dado que se detectará un posible abuso durante las revisiones de código, no debe tener miedo de dar esta posibilidad a los desarrolladores. Esto es similar a la posibilidad de excluir algunas partes del código de los cheques por parte de los linters o los correctores de estilo. JSLint, StyleCop y Code Analysis son tres ejemplos en los que se admite la exclusión y en realidad es útil sin alentar el abuso.
Considere el siguiente código:
No hay forma de crear un caso de prueba que llegue a esa otra rama. Sin embargo, si este fuera un software de vuelo crítico para la seguridad, las personas estarían en todo el caso del autor si esa protección contra el envío de un valor negativo
sqrt
no estuviera presente. Típicamente, el cálculorsq = a*a + b*b
y la extracción de la raíz cuadrada están separados por múltiples líneas de código. Mientras tanto, un rayo cósmico puede activar el bit de signorsq
.De hecho, el software de vuelo ha invocado el equivalente de
handle_this_impossible_event()
varias veces. Por lo general, esto implica cambiar el control a una computadora redundante, apagar con gracia la computadora sospechosa, reiniciar la computadora sospechosa y, finalmente, la computadora sospechosa asume el rol de copia de seguridad. Eso es mucho mejor que la computadora de vuelo principal enloqueciendo.Incluso en el software de vuelo, es imposible lograr una cobertura de código del 100%. Las personas que afirman haber logrado esto tienen un código trivial o no tienen suficientes pruebas contra estos eventos imposibles.
fuente
a
yb
son enteros de 32 bits con signo, muchos valores como 65535 y 65535 o 40000 y 40000 podrían resultarrsq
negativos.0.0
, lo que implica esoa
yb
son algunos tipos de punto flotante. Con el software de vuelo, es imperativo protegerse contra la raíz cuadrada de un número negativo, incluso si sabe que el número no puede ser negativo. Los rayos cósmicos son pequeñas cosas molestas. Un experimento muy reciente ( lanzado hace menos de una semana ) estudiará si una supercomputadora en la Estación Espacial Internacional puede usar software en lugar de hardware para protegerse contra los rayos cósmicos (SEU, etc.).0.0
.La cobertura de prueba es una métrica útil para la salud general de su proyecto. Una cobertura de prueba alta le permite tomar una decisión informada sobre si el software funcionará como se espera cuando se implemente; con una cobertura de prueba baja que implica que simplemente estás adivinando. Existen herramientas para medir la cobertura automáticamente, estas generalmente funcionan ejecutando el programa en un contexto de depuración o inyectando operaciones de contabilidad en el código ejecutado.
Existen diferentes tipos de pruebas y diferentes tipos de métricas de cobertura. Las métricas de cobertura comunes incluyen cobertura de función, cobertura de estado de cuenta, cobertura de sucursal y cobertura de condición, aunque hay más .
Las pruebas unitarias verifican si la implementación de una unidad conceptual (módulo, clase, método, ...) se ajusta a su especificación (en TDD, la prueba es la especificación). Las unidades sin sus propias pruebas unitarias son una señal de alerta, aunque podrían estar cubiertas por pruebas de estilo de integración.
Las pruebas unitarias deberían implicar una cobertura casi total de la función, ya que la prueba unitaria ejercita toda la interfaz pública de esa unidad, no debería haber ninguna funcionalidad que no sea tocada por estas pruebas. Si está introduciendo pruebas unitarias a una base de código existente, la cobertura de la función es un indicador de progreso aproximado.
Una prueba unitaria debe esforzarse por una buena cobertura del estado de cuenta (75% –100%). La cobertura del estado de cuenta es una medida de calidad para una prueba unitaria. La cobertura total no siempre es posible, y probablemente tenga un mejor uso de su tiempo que para mejorar la cobertura más allá del 95%.
La cobertura de sucursales y condiciones es más complicada. Cuanto más complicado o importante sea un código, mayores serán estas métricas. Pero para un código poco espectacular, la alta cobertura de las declaraciones tiende a ser suficiente (y ya implica una cobertura de sucursal de al menos el 50%). Mirar el informe de cobertura de condición de una unidad puede ayudar a construir mejores casos de prueba.
Las pruebas de integración verifican si varias unidades pueden funcionar correctamente entre sí. Las pruebas de integración pueden ser muy útiles sin obtener una puntuación alta en ninguna métrica de cobertura. Mientras que las pruebas de integración usualmente ejercitarían una gran parte de las interfaces de su unidad (es decir, tienen una alta cobertura de función), los componentes internos de estas unidades ya han sido cubiertos por las pruebas unitarias.
Ejecutar pruebas antes de fusionar el código en una rama principal es una buena idea. Sin embargo, calcular las métricas de cobertura de prueba para todo el programa tiende a tomar mucho tiempo; este es un buen trabajo para una construcción nocturna. Si puede descubrir cómo hacer esto, un buen compromiso sería ejecutar solo pruebas modificadas o pruebas unitarias en unidades modificadas en un gancho Git. Las fallas en las pruebas no son aceptables para nada más que los compromisos de "trabajo en progreso". Si las métricas de cobertura seleccionadas caen por debajo de algún umbral (por ejemplo, la cobertura de la declaración por debajo del 80%, o la introducción de nuevos métodos sin las pruebas correspondientes), estos problemas deben tratarse como una advertencia, con una oportunidad para que el desarrollador solucione estos problemas potenciales. Sin embargo, a veces hay buenas razones para ignorar estas advertencias, y los desarrolladores deberían poder hacerlo.
Las pruebas son buenas, pero demasiado puede ser molesto. La retroalimentación rápida y relevante puede ayudar a fomentar la atención a la calidad, pero no desea que interfiera en la producción de valor. Personalmente, prefiero ejecutar pruebas manualmente, ya que me permite obtener comentarios más rápidos sobre la parte en la que estoy trabajando. Antes del lanzamiento, haré un enfoque de calidad donde usaré análisis estático, perfiladores y herramientas de cobertura de código para encontrar zonas problemáticas (algunos de estos pasos forman parte de un conjunto de pruebas de prelanzamiento).
fuente
Nadie ha mencionado las pruebas de mutación . La idea detrás de ellos es bastante práctica e intuitiva.
Funcionan modificando el código fuente al azar (por ejemplo, cambiando ">" a "<"), por lo tanto, mutación, y verificando si estos cambios fortuitos rompen cualquier prueba.
Si no lo hacen, entonces a) el código en cuestión podría ser innecesario, o b) (más probablemente) este fragmento de código no está cubierto por una prueba, ya que romperlo no se detecta.
fuente
Por supuesto, los datos de cobertura de código se pueden obtener automáticamente, pero no se deben tomar decisiones automáticas basadas en ellos, por razones que otros ya han explicado. (Demasiado borroso, demasiado margen de error).
Sin embargo, lo mejor es tener un proceso establecido mediante el cual el estado actual del proyecto en términos de cobertura de código sea revisado regularmente por seres humanos, posiblemente con informes diarios que lleguen a la bandeja de entrada del gerente del proyecto.
En entornos empresariales, esto se logra con herramientas de integración continua como Hudson, Jenkins, etc. Estas herramientas están configuradas para verificar regularmente todo el proyecto desde el repositorio de código fuente, construirlo, ejecutar las pruebas y generar informes. Por supuesto, se pueden configurar para ejecutar las pruebas en modo de cobertura de código e incluir los resultados en estos informes.
Jetbrains también hace TeamCity, que me parece un poco más ligero y adecuado para tiendas de software más pequeñas.
Por lo tanto, el gerente del proyecto recibe informes regulares de cobertura de código, usa su propio buen juicio y actúa como ejecutor si es necesario.
fuente
La cobertura del código se puede verificar automáticamente, a pesar de la opinión popular, el conjunto de herramientas Rational's Purify incluye una función de cobertura del código. Se basó en la instrumentación de todas las funciones (trabajó en los archivos binarios, actualizando cada función o llamada con un poco de código extra) para poder escribir datos que luego se mostraban al usuario. Tecnología bastante buena, especialmente en ese momento.
Sin embargo, incluso cuando intentamos realmente, realmente difícil obtener el 100% de cobertura, ¡solo logramos el 70% más o menos! Así que es un ejercicio un poco inútil.
Sin embargo, en la situación de escribir pruebas unitarias, creo que el 100% de cobertura de pruebas unitarias es aún más inútil. ¡Pruebe los métodos que requieren pruebas unitarias, no todos los captadores o colocadores! Las pruebas unitarias deben consistir en verificar las funciones difíciles (o las clases TBH) y no tratar de marcar casillas en algún proceso o herramienta que muestre buenos tics verdes.
fuente
He creado una herramienta para esto
https://github.com/exussum12/coverageChecker
Utilizando
Fallará si menos del 70% de la diferencia está cubierta por pruebas unitarias.
Obtenga la diferencia por.
Asumiendo que se ramificó de maestro y se fusionará nuevamente en maestro
Ignore la bandera phpunit en el código, realmente es solo una verificación de trébol para que cualquier cosa que pueda generar trébol pueda usarla.
Como otras respuestas sugirieron, poner esto al 100% no es una buena idea
fuente