Affichage des articles dont le libellé est jacoco. Afficher tous les articles
Affichage des articles dont le libellé est jacoco. Afficher tous les articles

vendredi 17 janvier 2014

Unit tests and integration tests coverage in sonar with gradle

I recently needed to configure a multi-module gradle project in order to generate unit test, integration test and overall coverage indicators in sonar. As it wasn't so obvious I thought it would be a good idea to share my example.

The goal is to generate the following report in sonar :


Complete gradle file


So here is my complete build.gradle file :

apply plugin: 'sonar-runner'

allprojects {
  apply plugin: 'java'
  apply plugin: 'jacoco'

  sourceSets {
    integtest {
      java {
        compileClasspath += main.output
        runtimeClasspath += main.output
        srcDir 'src/integtest/java'
      }
    }
  }

  configurations {
    integtestCompile.extendsFrom testCompile
  }

  task "integtest"(type: Test, dependsOn: integtestClasses) {
    testClassesDir = sourceSets.integtest.output.classesDir
    classpath = sourceSets.integtest.runtimeClasspath

      jacoco {
          destinationFile = file("$buildDir/jacoco/jacocoIntegTest.exec")
      }
  }

  test {
    jacoco {
      destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
    }
  }

  sonarRunner {
    sonarProperties {
      property "sonar.jacoco.reportPath", "$buildDir/jacoco/jacocoTest.exec"
      property "sonar.jacoco.itReportPath", "$buildDir/jacoco/jacocoIntegTest.exec"
    }
  }
}

sonarRunner {
    sonarProperties {
        property "sonar.projectName", "test-samples"
        property "sonar.projectKey", "jsebfranck.samples"
    }
}

Explanations

I used Jacoco to generate my tests coverage indicators :

  apply plugin: 'jacoco'


The following lines allow to configure my integration tests. To distinguish these tests from the unit tests, I moved them in a specific source folder : "src/integtest/java". Please note that with gradle, the default test folder is "src/test/java" and I use it for my unit tests.

  sourceSets {
    integtest {
      java {
        compileClasspath += main.output
        runtimeClasspath += main.output
        srcDir 'src/integtest/java'
      }
    }
  }

  configurations {
    integtestCompile.extendsFrom testCompile
  }

  task "integtest"(type: Test, dependsOn: integtestClasses) {
    testClassesDir = sourceSets.integtest.output.classesDir
    classpath = sourceSets.integtest.runtimeClasspath
  }

I configured Jacoco to generate the tests coverage data in a specific directory : one for the unit tests and for the integration tests :

  task "integtest"(type: Test, dependsOn: integtestClasses) {
    testClassesDir = sourceSets.integtest.output.classesDir
    classpath = sourceSets.integtest.runtimeClasspath

      jacoco {
          destinationFile = file("$buildDir/jacoco/jacocoIntegTest.exec")
      }
  }

  test {
    jacoco {
      destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
    }
  }

Then for each module, I configured sonar to use generated Jacoco data :
  • reportPath property allows to configure the unit tests coverage
  • itReportPath property allows to configure the integration tests coverage
allprojects {
  sonarRunner {
    sonarProperties {
      property "sonar.jacoco.reportPath", "$buildDir/jacoco/jacocoTest.exec"
      property "sonar.jacoco.itReportPath", "$buildDir/jacoco/jacocoIntegTest.exec"
    }
  }
}

Finally I configured my sonar instance. Here I use the default parameters so the report is generated on my localhost sonar installation and its h2 database :

sonarRunner {
    sonarProperties {
        property "sonar.projectName", "test-samples"
        property "sonar.projectKey", "jsebfranck.samples"
    }
}


Source code

Please find the complete source code on my github repository about tests.