文章目录
起因
最近新写了一个项目,为了更好的保证项目输出的质量,引入了单元测试覆盖率统计框架Jacoco
。由于gradle官网上的案例只有几个默认的task(test、JacocoTestReport等)
的设置,而我希望能够额外为不同的层提供单独的test
,也就发生了接下来这些有趣的事儿。
1. 为什么JacocoTestReport
总是被SKIPPED
首先,我写了一个自定义的test。并且通过将finalizedBy
指定为JacocoTestReport
来让test执行完毕后自动执行JacocoTestReport
。自定义test以及JacocoTestReport
如下:
//自定义test
task serviceTest(type: Test) {
useTestNG()
useJUnitPlatform()
finalizedBy jacocoTestReport
jacoco {
enabled = true
//指定原始数据文件位置
destinationFile = layout.buildDirectory.file("jacoco/${taskName}.exec").get().asFile
includes = ['xxxservice']
excludeClassLoaders = []
includeNoLocationClasses = false
sessionId = "<auto-generated value>"
output = JacocoTaskExtension.Output.FILE
}
}
jacocoTestReport {
// tests are required to run before generating the report
dependsOn serviceTest
//指定覆盖率统计数据文件。
executionData(layout.buildDirectory.file("jacoco/${serviceTest.name}.exec").get().asFile)
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, include: ['xxxservice'])
}))
}
reports {
xml.required = false
csv.required = false
html.outputLocation = layout.buildDirectory.dir('jacocoReport')
}
}
看起来似乎没啥问题,该做的都做了。但是执行的时候程序却跳过了jacocoTestReport。当时特别纳闷,就去网上提了个问题。最后gradle官方的工作人员给了答复,大概意思是executionData
对应的文件不存在,在jacocoTestReport
里加上onlyIf = {true}
可以保证jacocoTestReport
会执行,并且执行最终会报出test.exec文件不存在的错误。ok,有方向了,那就一个一个来分析。
2. task
里的onlyIf
事实上,onlyIf
决定了task
是否被执行。同时,onlyIf
可以设置多个规则判断,如果所有的规则判断都返回为true
,才会执行task
。否则,跳过task
。
2.1 SkipOnlyIfTaskExecuter
让我们进入SkipOnlyIfTaskExecuter
一探究竟:
public class SkipOnlyIfTaskExecuter implements TaskExecuter {
@Override
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
boolean skip = !task.getOnlyIf().isSatisfiedBy(task);
//跳过task
if (skip) {
return TaskExecuterResult.WITHOUT_OUTPUTS;
}
//执行task
return executer.execute(task, state, context);
}
//遍历所有规则
public boolean isSatisfiedBy(T object) {
Spec<? super T>[] specs = getSpecsArray();
for (Spec<? super T> spec : specs)