1
votes

I have the following environment: JDK 7 + Gradle 1.5 + Jacoco 0.6.2 + Tomcat 7.0.29 (complete code at my GIST https://gist.github.com/marcellodesales/5496686).

The following build.gradle is my current build script from where I try to run code coverage from an integration test written in Rest-Assured for a Restful API. I have tried the Jacoco plugin (org.ajoberstar:gradle-jacoco:0.3.0) and I've tried to use Jacoco from the Jars and tried using the Agent but it is not even started (https://stackoverflow.com/a/16035811/433814).

/*******  Java project plugin *******/
apply plugin: 'java'

/******* IDE plugins ********/
apply plugin: 'eclipse'

/******* Deployment + Test Plugins ******/
apply plugin: 'maven'
apply plugin: 'tomcat'
apply plugin: 'jacoco'

buildscript {

  repositories {
    mavenCentral()
  }
  //******************* Supporting Embedded Tomcat
  dependencies {
    classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:0.9.8'
    classpath 'org.ajoberstar:gradle-jacoco:0.3.0'
  }

}

sourceCompatibility = 1.7
targetCompatibility = 1.7

sourceSets {
  integrationTest {
    java.srcDir file('src/integration-test/java')
    resources.srcDir file('src/integration-test/resources')
  }
}

repositories {
  mavenCentral()
}

dependencies {
  compile 'com.sun.jersey:jersey-client:1.17'
  compile 'com.sun.jersey:jersey-server:1.17'
  compile 'com.sun.jersey:jersey-servlet:1.17'
  compile 'com.sun.jersey:jersey-core:1.17'
  compile 'com.sun.jersey:jersey-json:1.17'
  compile 'com.sun.jersey.contribs:jersey-multipart:1.17'
  compile 'com.google.guava:guava:13.0.1'
  compile 'com.google.code.gson:gson:2.2.2'
  compile 'com.octo.captcha:jcaptcha-all:1.0-RC6'
  compile 'commons-io:commons-io:2.4'
  compile 'javax.ws.rs:jsr311-api:1.1.1'
  providedCompile 'javax.servlet:javax.servlet-api:3.0.1', 'javax.servlet:jsp-api:2.0'
  compile 'log4j:log4j:1.2.17'
  compile 'nl.captcha:simplecaptcha:1.2.1'
  compile group: 'net.sf.json-lib', name: 'json-lib', version: '2.3', classifier: 'jdk15' 
  compile 'org.apache.commons:commons-codec:1.3'
  compile 'org.apache.commons:commons-io:1.3.2'
  compile 'org.codehaus.jackson:jackson-core-asl:1.9.12'
  compile 'org.codehaus.jackson:jackson-xc:1.9.12'
  compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.12'
  compile 'org.codehaus.jackson:jackson-jaxrs:1.9.12'
  compile 'xom:xom:1.1'

  // UNIT Tests
  testCompile 'junit:junit:4.11'

  // Integration Tests
  testCompile 'com.jayway.restassured:rest-assured:1.8.0'
  testCompile 'com.jayway.restassured:json-path:1.8.0'
  testCompile 'org.codehaus.groovy:groovy-all:2.1.3'

  integrationTestCompile sourceSets.main.output
  integrationTestCompile configurations.testCompile
  integrationTestCompile sourceSets.test.output
  integrationTestRuntime configurations.testRuntime

  // Embedded Tomcat Support
  def tomcatVersion = '7.0.29'
  tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
         "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
  tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
    exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
  }

}

// set source file encoding for all compile tasks
tasks.withType(Compile) {
  options.encoding = 'UTF-8'
}

jacoco {
  // change the version of Jacoco in use
  toolVersion = '0.6.2+'
}

test {
  maxParallelForks = 5
  forkEvery = 5

  jacoco {
    // would have been enabled by default
    enabled = true
  }

}

// ########################### Embedded Tomcat Support ###############################
tomcatRun {
  httpPort = 8080
}

[tomcatRun, tomcatRunWar, tomcatStop]*.stopPort = 8081
[tomcatRun, tomcatRunWar, tomcatStop]*.stopKey = 'stopKey'
[tomcatRun, tomcatRunWar]*.outputFile = project.file("$buildDir/tomcat.log")

// ########################## Integration Tests ###############################

task integrationTest(type: Test, dependsOn: jar, description: 'Runs the integration tests.', group: 'verification') {
  println "Starting the integration tests"
  testClassesDir = sourceSets.integrationTest.output.classesDir
  classpath = sourceSets.integrationTest.runtimeClasspath
  testLogging.showStandardStreams = true

  jacoco {
    // would have been enabled by default
    enabled = true
  }
}

integrationTest.doFirst {
  println 'Starting the embedded tomcat server'
  tasks.tomcatRun.daemon=true
  tasks.tomcatRun.execute()
}

integrationTest.doLast {
  println 'Stopping the embedded tomcat server'
  tasks.tomcatStop.execute()
}

import org.ajoberstar.gradle.jacoco.tasks.*

task testReport(type: JacocoReport) {
  executionData test

    // specify one or more source sets that you want to report on the coverage of
    sourceSets project.sourceSets.main

    destPath 'build/reports/coverage-unit'
}

task integrationTestReport(type: JacocoReport) {
    // can include one or more execution files
    executionData integrationTest

    // specify one or more source sets that you want to report on the coverage of
    sourceSets project.sourceSets.main

    destPath 'build/reports/coverage-integration'
}

gradle.taskGraph.afterTask { task ->
   if (task == test) {
     tasks.testReport.execute()
   }
   if (task == integrationTest) {
     tasks.integrationTestReport.execute()
   }
}

After trying using the Plugin, I decided to run Jacoco manually from the Jars. A complete application can be downloaded at https://github.com/marcellodesales/gradle-rest-assured-selenium-jacoco. Here's the script snippet with the change to add the Jvm options to add the JVM options:

task integrationTest(type: Test, dependsOn: jar, description: 'Runs the integration tests.', group: 'verification') {
  testClassesDir = sourceSets.integrationTest.output.classesDir
  classpath = sourceSets.integrationTest.runtimeClasspath
  systemProperties['jar.path'] = jar.archivePath

  // use JaCoCo agent to record execution coverage data
  jvmArgs "-javaagent:$configurations.jacoco.asPath=destfile=$buildDir/jacoco-int.exec"
}
check.dependsOn integrationTest

integrationTest.doFirst {
  println 'Starting the embedded tomcat server'
  tasks.tomcatRun.daemon = true
  tasks.tomcatRun.execute()
}

integrationTest.doLast {
  println 'Stopping the embedded tomcat server'
  tasks.tomcatStop.execute()
}
1

1 Answers

2
votes

In your sample code you configured your build script to run coverage for your integTests instead of your production code. Do you want to collect coverage data for the API used to communicate with the tomcat server or do you want to collect coverage data for the code running on the tomcat. For the latter, you have to instrument the code executed in the tomcat jvm instead of the integTest code. Therefor you have to add the javaagent setup to the 'tomcatRun' task.

hope that helped,

cheers,

René