Tendemos a asociar la cobertura de código de manera casi exclusiva a las pruebas unitarias. Sin duda, es muy relevante la cobertura de nuestras pruebas a la hora de poder estimar en que medida nos protegen de regresiones y errores. Además cuando escribimos pruebas, la cobertura nos proporciona información de suma relevancia a la hora de saber que porciones de nuestro código carecen en absoluto de pruebas y, en consecuencia, ilumina aquellos lugares donde debemos centrar nuestro esfuerzos. Una cobertura alta no garantiza unas pruebas unitarias excelentes, pero si es cierto, que sin la más alta cobertura posible, nuestras pruebas unitarias nunca serán excelentes.
Sin perjuicio de lo anterior es cierto que existen otros escenarios, menos conocidos, en los que observar la cobertura del código nos puede ayudar de manera significativa.
Debemos tener en cuenta que la cobertura de código nos proporciona información sobre el código de nuestra aplicación que se ha ejecutado, lo que muchas veces obviamos es que esa ejecución no tienen por qué estar provocada por la ejecución de pruebas unitarias.
Dicho esto, un primer escenario en el que me he encontrado interés en conocer la cobertura, es cuando se ejecutan pruebas manuales. En las pruebas manuales un tester o una herramienta de automatización de pruebas interactúa con el sistema en busca de errores o con el interés de certificar su ausencia. Generalmente nos se suele recoger la cobertura de este tipo de pruebas si bien es cierto que puede proporciona información valiosa: ¿Qué partes de código se utilizan en cada escenario? ¿Qué partes del código no son ejercitadas por las pruebas? ¿Qué partes del código son ejecutadas por más de una prueba? ¿Cubrimos mediante pruebas manuales aquellas partes del código no probadas por las pruebas unitarias?… Seguro que se os ocurren algunas cuestiones más, según cual sea vuestro escenario.
Otro escenario en el que la información sobre la cobertura es útil es cuando estamos depurando un error. ¿Cuántas veces no os habéis enfrentado a un error y a pesar de poderle reproducir habéis tenido problemas para saber en que parte del código se producía?.
En ambos escenarios y seguro que en algún otro, conocer que código se ha ejecutado nos puede ser de gran utilidad. Pero ¿cómo recoger información de cobertura de un código que no se ha ejecutado desde las pruebas unitarias ni, probablemente, desde dentro de Visual Studio?
Las herramientas de línea de comandos de Visual Studio pueden ayudarnos. En concreto, tenemos que usar vsinstr en primera instancia, que nos permite instrumentalizar un ensamblado para poder recuperar la información de cobertura del código asociado al ensamblado. Luego usamos vsperfmon (también se puede utilizar vsperfcmd) para recopilar esa información. Para poder analizar la información recopilada de manera coherente es necesario contar con los pdb asociados al ensamblado.
Supongamos que tenemos un ensamblado llamado MyAssembly.exe.
La siguiente instrucción instrumenta el ensamblado (el ensamblado original será renombrado):
vsinstr /coverage MyAssembly.exe
Luego con la siguiente instrucción comenzaremos la monitorización de la cobertura. Bastará ejecutar aquellos escenarios de nuestra aplicación sobre los que queremos recoger información de cobertura:
vsperfmon /coverage /output:cobertura.coverage
La información sobre la cobertura quedará recogida en el archivo cobertura.coverage, que podremos estudiar con Visual Studio de manera gráfica, con el código cubierto y no coloreado (si es que se encuentra disponible), tal y como acostumbramos cuando vemos la cobertura de nuestras pruebas.
Señalar que tanto vsinstr como vsperfmon se encuentran en el directorio Team ToolsPerformance Tools del directorio de instalación de Visual Studio.
¡Espero que esta técnica os resulte útil!