Jenkins nos permite extender los tres pasos básicos de la integración continua que vimos en el post anterior añadiendo uno mas que vele por la cobertura de las pruebas unitarias y el análisis estático de la calidad del código. Examinaremos, en este post, las opciones que tenemos para lograrlo.

Cobertura del código

Si tenemos proceso de integración bien configurado debemos cuidar que todos escriban sus pruebas unitarias. El hecho de que el código compile y los jobs de Jenkins sean exitosos no significa que el código funcionara como se espera.

La solución es agregar una herramienta de cobertura de código que corre todas las pruebas y verifica que partes del código están propiamente cubiertas. Luego esta herramienta crea un reporte mostrando todos los escenarios que no fueron probados. Pero lo mas importante es, que marca como fallido el proceso de compilación si la cobertura de las pruebas baja de un porcentaje estandar.

Hay muchas herramienatas disponibles para analizar la cobertura del código. Para Java las mas populares son>

Para efectos de ejemplificar usaremos JaCoCo y su configuración en jenkins.

Los pasos que debemos seguir para lograrlo, asumiendo que estamos trabajando con gradle, son:

  1. Agregar JaCoCo a la configuración de Gradle
  2. Agregar un stage de cobertura a nuestro pipeline
  3. Opcionalmente publicar el reporte de cobertura en jenkins

Agregando JaCoCo a Gradle

Para agregar JaCoCo desde Gradle, necesitamos agregar el plugin jacoco al archivo build.gradle con la siguiente linea:

apply plugin: "jacoco"

Lo siguiente es que tenemos que hacer que Gradle falle en caso de que la cobertura del código sea demasiado baja. Para ello agregamos las siguientes instrucciones a nuestro archivo build.gradle

jacocoTestCoverageVerification {
    violationRules {
        rule {
           limit {
               minimum = 1.0
           }
        }
     }
}

En este caso hemos configurado un limite agresivo del 100% de cobertura. Pero si quisiéramos usar uno mas conservador, digamos 80%, simplemente asignamos un valor mas pequeño a la variable minimum. Para un 20% sería 0.20.

Finalmente corremos el análisis de cobertura:

$ ./gradlew test jacocoTestCoverageVerification

El comando verifica que la cobertura sea al menos 100% y genera un reporte con el siguiente comando:

$ ./gradlew jacocoTestReport

Este reporte lo podemos revisar en la ruta: /build/reports/jacoco/test/html/index.html

Agregando un stage de cobertura

En el post donde aprendimos a hacer un pipeline, vimos los 3 stages básicos. Ahora agregamos uno mas para verificar la cobertura del código así:

stage("Cobertura") {
    steps {
        sh "./gradlew jacocoTestReport"
        sh "./gradlew jacocoTestCoverageVerification"
    }
}

Así, después de agregar este stage, si a alguien se le ocurre enviar código al repositorio que no esta con una cobertura del 100%…

El build falla….

Publicar el reporte de cobertura

Cuando la cobertura del código es baja y el pipeline falla, a menudo es útil echarle un ojito al reporte de cobertura. Podríamos correr el comando gradle localmente para verlo, pero…

Nadie tiene tiempo para eso!

Entonces para publicar el reporte, necesitamos ampliar un poco la definición del stage

stage("Code coverage") {
    steps {
        sh "./gradlew jacocoTestReport"
        publishHTML (target: [
            reportDir: 'build/reports/jacoco/test/html',
            reportFiles: 'index.html',
            reportName: "Reporte JaCoCo"
        ])
        sh "./gradlew jacocoTestCoverageVerification"
    }
}

Esta definición copia el reporte que JaCoCo genera a la salida de Jenkins. Cuando ejecutemos la compilación de nuevo, deberíamos ver un link al reporte de cobertura justo abajo del link que pone “Build Now”

Análisis de código estático

Ahora bien, el código podría funcionar a la perfección pero aun así podría ser un autentico espagueti en términos de buenas prácticas y convenciones de estilo. Todos sabemos que el código bien hecho es fácil de mantener.

El análisis estático del código es una proceso automático mediante el cual se revisa el código sin necesidad de ejecutarlo. En la mayoría de los casos implica revisar un conjunto de reglas en el código fuente. Estas reglas podrían aplicarse a un rango muy amplio de aspectos. Por ejemplo podríamos definir una regla para que todas las clases publicas en un proyecto java tengan un comentario con el formato javadoc; otra mas para que el máximo de caracteres en una linea sea de 120, o si definimos una clase que implemente el método equals() obligatoriamente implemente el método hashCode().

Hay muchas herramientas populares para el análisis de código estático, entre ellas tenemos:

Para efectos de ejemplificar vamos a integrar con nuestro pipeline CheckStyle. Para ello similarmente al análisis de cobertura tenemos tres pasos a seguir:

  1. Agregar la configuración del CheckStyle
  2. Agregar el stage al pipeline
  3. Opcionalmente publicar el reporte de calidad en Jenkins

Configurar CheckStyle

Lo primero que tenemos que hacer es crear un archivo de configuración. Esto lo hacemos creándolo en la siguiente ruta:  config/checkstyle/checkstyle.xml

El archivo de configuración básico debería verse algo así:

<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="Checker">
    <module name="TreeWalker">
        <module name="JavadocType">
            <property name="scope" value="public"/>
        </module>
    </module>
</module>

Ademas necesitamos que nuestro proyecto Gradle entienda que tienen que aplicar estas reglas. Para ello agregamos el plugin a nuestro archivo gradle.build

apply plugin: 'checkstyle'

Ahora podemos efectuar una revisión de estilo corriendo el comando de gradle:

$ ./gradlew checkstyleMain

Para mas información de como configurar propiamente este plugin, vean la documentación oficial

Agregar el stage de análisis estático

Como en pasos anteriores, simplemente agregamos un nuevo stage.

stage("Análisis de código estático") {
    steps {
        sh "./gradlew checkstyleMain"
    }
}

Después de aplicar este stage, si alguien decide que va a hacer un commit con código que solo el y Dios pueden leer…

Fallo en el stage de quality gate

Publicar el reporte de CheckStyle

Similarmente a como publicamos el reporte de JaCoCo, podemos publicar el reporte de CheckStyle añadiendo la siguiente directiva:

publishHTML (target: [
    reportDir: 'build/reports/checkstyle/',
    reportFiles: 'main.html',
    reportName: "Reporte Checkstyle"
])

Conclusión

Jenkins ofrece herramientas suficientes y fáciles de usar para que nuestro código no solo compile, si no que también sea hermoso 🙂

En una organización en donde los equipos crecen, es necesario aplicar estas practicas en la integración continua como un esfuerzo continuo de que la base de código sea fácil de mantener a largo plazo.