Runing Tests and Code Coverage without Visual Studio. OpenCover con coverlet y ReportGenerator.

imageMuy buenas,

Llevo ya un tiempo con ganas de escribir sobre este tema y, principalmente por el impacto que causa en DevOps, en donde últimamente estoy un poco más inmerso de lo habitual.

En primer lugar, me gustaría hacer mención a este post del compañero @snavarropino, donde nos habla de la Cobertura de Código y Azure DevOps (anteriormente conocido como VSTS).

Y, en segundo lugar quiero hacer mención también a esta reseña de Wikipedia:

La cobertura de código es una medida (porcentual) en las pruebas de software que mide el grado en que el código fuente de un programa ha sido comprobado. Sirve para determinar la calidad del test que se lleve a cabo y para determinar las partes críticas del código que no han sido comprobadas y las partes que ya lo fueron.

Cuando desarrollamos con Visual Studio, y ejecutamos tests, en la mayoría de las ocasiones hacemos uso del tooling integrado en Visual Studio, si bien, tenemos que reconocer que para poder lanzar la cobertura de código entre otras acciones que brinda, necesitamos disponer de la edición Enterprise, lo que supone un coste adicional, que en muchas ocasiones es tal que da lugar a evaluar y analizar el mismo frente al beneficio que aporta.

A continuación veremos como ejecutar los Tests y la Cobertura de código desde Visual Studio, tal y como estamos acostumbrados y también, desde la línea de comandos, con .Net Core.

Desde Visual Studio (Enterprise Edition)

Lanzamos la cobertura de código bien desde la opción de menú “Test – Analyze Code Coverage” o bien, desde el Test Explorer, “Analyze Code Coverage for Selected Tests”:

image

El resultado es el siguiente:

image

Donde, por ejemplo, para la clase ProjectService.cs, podemos ver que parte del código está cubierto (en azul) por los tests y que partes no.

image

Teniendo en cuenta esto, podemos ir afinando nuestros tests para cubrir más y más código. Existen indicadores referentes a este dato que sirven de orientación para medir la calidad de nuestros desarrollos, si bien, no olvidemos que la cobertura determina la calidad del test, (no la del código). Eso si, podremos conocer el porcentaje de código que es cubierto y en consecuencia asegurar que tal %, al menos está “testeado”, lo que supone una garantía de calidad.

Conseguir un 100% de cobertura, evidentemente supone un esfuerzo y un coste, y es aquí donde debemos poner especial atención. Tenemos que valorar el porcentaje a cubrir en base a este coste y tiempo. Un valor de este porcentaje orientativo puede estar entre el 60% y el 70%, pero va a depender de cada caso en particular.  Dejo aquí una referencia de Wikipedia, a: El Triangulo de Hierro (o Iron Triangle), para profundizar en este tema, al que quizás, otro día le dedique un post.

Desde Línea de Comandos (Sin Visual Studio)

Antes de continuar, es importante recordar que los tests han de ser excluidos de la cobertura indicándolo mediante el atributo [ExcludeFromCodeCoverage] a nivel de clase en los tests.  De igual forma, podemos también excluirlos haciendo uso del fichero “.runsettings”. Visitar este enlace, para más detalle.

Adicionalmente, añadir el paquete Nuget: “coverlet.msbuild”.

image

A continuación, en el siguiente fragmento de código, (“coverage.cmd”) contamos con todas las instrucciones para ejecutar los tests y visualizar la cobertura de código de forma similar a como lo hace Visual Studio.

Las líneas [19-24, se corresponden con el comando “dotnet test” que ejecuta los tests unitarios. Habilitan la cobertura de código, especifican el formato en el que generar la cobertura (“Open Cover”) y la ruta en la que se generará el fichero “.xml” con el resultado de la cobertura.

Si ejecutamos este comando, obtendremos la siguiente salida en relación a la cobertura de código:

image

Donde, podemos ver la cobertura para cada módulo y diferenciada por:

  • Línea. Número de líneas de código que son cubiertas.
  • Branch. Número de caminos diferentes que toma el código (para instrucciones, if, switch, etc.), que son cubiertos.
  • Método. Número de métodos que son invocados desde los tests.

Adicionalmente, podríamos utilizar el parámetro /p:Exclude=\”[].Models.*\”, para excluir del análisis, cualquier clase cuyo namespace coincida con el filtro indicado. Mas detalle aquí: coverlet.msbuild.

La línea 27. Instala la herramienta Report Generator, que va a permitirnos generar un informe similar al utilizado por Visual Studio.

La línea 28.  Ejecuta la herramienta, tomando como entrada uno o más ficheros (en formato .xml) generado tras la ejecución de los tests, indicado por el parámetro “p:/CoverletOutput” y como salida, –targetdir, la ruta en la que se generan los ficheros de informes en el formato especificado por el parámetro –reporttypes (Html y HtmlSummary).

Finalmente, la línea 30, lanza el navegador y muestra el fichero “index.htm” tal y como podemos ver en la siguiente imagen, con el resumen y el detalle de la cobertura.

image

¡Ahora ya no hay argumentos para no “cubrir” bien el código!

En siguientes posts, veremos como aplica todo esto a la Integración Continua dentro del mundo de DevOps, tanto en Jenkins, como en Travis, como en Azure DevOps.

Happy testing and good Coverage
Juanlu