gradle虽好,但是默认没有对代码覆盖的支持,还是官网的cook book里面有 一段已经很好用的脚本可以完成这个功能,搞录如下:
usePlugin('java')
def cobSerFile="${project.buildDir}/cobertura.ser"
def srcOriginal="${sourceSets.main.classesDir}"
def srcCopy="${srcOriginal}-copy"
repositories {
mavenCentral()
}
dependencies {
testRuntime 'net.sourceforge.cobertura:cobertura:1.9.3'
testCompile 'junit:junit:4.5'
}
test.doFirst {
ant {
// delete data file for cobertura, otherwise coverage would be added
delete(file:cobSerFile, failonerror:false)
// delete copy of original classes
delete(dir: srcCopy, failonerror:false)
// import cobertura task, so it is available in the script
taskdef(resource:'tasks.properties', classpath: configurations.testRuntime.asPath)
// create copy (backup) of original class files
copy(todir: srcCopy) {
fileset(dir: srcOriginal)
}
// instrument the relevant classes in-place
'cobertura-instrument'(datafile:cobSerFile) {
fileset(dir: srcOriginal, includes:"my/classes/**/*.class", excludes:"**/*Test.class")
}
}
}
test {
// pass information on cobertura datafile to your testing framework
// see information below this code snippet
}
test.doLast {
if (new File(srcCopy).exists()) {
// replace instrumented classes with backup copy again
ant {
delete(file: srcOriginal)
move(file: srcCopy, tofile: srcOriginal)
}
// create cobertura reports
ant.'cobertura-report'(destdir:"${project.buildDirName}/test-results", format:'html', srcdir:"src/main/java", datafile:cobSerFile)
}
}
gradle支持多工程,我把这段代码放到根工程build.gradle里的subprojects配置块中,但是在执行时一个子工程总是在测试时报找不到log4j类的异常。我以为是gradle, ant和cobertura所依赖的log4j的版本不同导致的,但是经过各种尝试,都不能解决问题。后来细读gradle手册,发现了gradle有个project-report插件,可以生成依赖关系图。通过这个图,我才发现那个子项目的testRuntime里面并没有log4j,但是事实上我已经添加了。一番思索后,才想起来,是由于那个子工程build.gradle里的如下脚本导致了问题:
def targetServer = System.properties['targetServer'] configurations {
['servlet-api'].each { runtime.exclude module: it }
if (targetServer == null || targetServer == 'jboss4') {
['activation', 'antlr', 'asm', 'asm-attrs', 'cglib', 'commons-codec', 'commons-collections', 'commons-pool', 'dom4j', 'ehcache', 'ejb3-persistence', 'hibernate', 'hibernate-annotations', 'hibernate-commons-annotations', 'hibernate-core', 'hibernate-validator', 'jta', 'log4j', 'mail', 'persistence-api', 'geronimo-jms_1.1_spec', 'geronimo-j2ee-management_1.1_spec'].each {
runtime.exclude module: it
}
}
}
这段脚本是为了在生成war的时候,不包含activation等jar包,因为这个war要部署到jboss服务器上,而jboss上已经包含这些jar包了。不幸的是testRuntime是继承于runtime配置的,从runtime里去掉指定的jar包后,testRuntime里也不再包含那些jar包了,这才会导致cobertura不能运行。解决的有法是使用war插件添加的两个新的配置providedCompile providedRuntime,这两个配置的jar包在编译期和测试期有效,但是却不会被打包到war里面。代码如下:
dependencies {
providedCompile 'javax.xml.bind:jaxb-api:2.2.1'
//...
providedRuntime 'log4j:log4j:1.2.13'
//...
// }