如何在 TestNG 和 JUnit 中使用 JaCoCo Gradle 插件?

How to use JaCoCo Gradle Plugin with TestNG and JUnit?

我正在开发一个项目,我们使用 TestNG 和 JUnit 进行测试。

不幸的是,在编写 TestNG 测试时,JaCoCo 覆盖率报告中并未考虑它们。

我写了一个 testng.gradle 文件,我将其包含在每个 build.gradle 文件中(这是一个多模块项目):

task testNG(type: Test) { useTestNG() }
test.dependsOn testNG

JUnit 和 TestNG 测试都是这样工作的。

如果我这样写 testng.gradle

test {
    useTestNG()
}

JaCoCo 工作正常,但显然只有 TestNG 测试被执行。

我该如何解决?这是 Gradle 的 JaCoCo 插件中的错误吗?

似乎虽然 Gradle JaCoCo Plugin 增强了 testNG 任务,所以它的执行使用 JaCoCo Java agent,但是它忘记更新 jacocoTestReport 任务,所以这个任务不使用 testNG 任务的执行结果。不知道这是错误还是故意的,但下面提供了解决方案。

证明这一点

文件src/main/java/Example.java:

public class Example {
  public void junit() {
    System.out.println("JUnit");
  }

  public void testng() {
    System.out.println("TestNG");
  }
}

文件src/test/java/ExampleJUnitTest.java:

import org.junit.Test;

public class ExampleJUnitTest {
  @Test
  public void test() {
    new Example().junit();
  }
}

文件src/test/java/ExampleTestNGTest.java:

import org.testng.annotations.Test;

public class ExampleTestNGTest {
  @Test
  public void test() {
    new Example().testng();
  }
}

文件build.gradle:

apply plugin: 'java'
apply plugin: 'jacoco'

repositories {
  mavenCentral()
}

dependencies {
  testCompile 'org.testng:testng:6.8.8'
  testCompile 'junit:junit:4.12'
}

task testNG(type: Test) {
  useTestNG()
}

test {
  dependsOn testNG
}

执行 gradle clean test jacocoTestReport -d 后,您将在日志中看到

java ... -javaagent:.../jacocoagent.jar=destfile=build/jacoco/testNG.exec ...
...
java ... -javaagent:.../jacocoagent.jar=destfile=build/jacoco/test.exec ...

目录 build/jacoco 包含两个文件 - testNG.exectest.exec,分别用于 testNGtest 任务。虽然 JaCoCo 报告仅显示 test 任务执行 JUnit。

解决这个问题

要么指示任务testNG将执行数据写入与test相同的文件:

task testNG(type: Test) {
  useTestNG()
  jacoco {
    destinationFile = file("$buildDir/jacoco/test.exec")
  }
}

要么指示任务 jacocoTestReport 也使用 testNG.exec 文件:

jacocoTestReport {
  executionData testNG
}

我假设对于 multi-module 项目的一般情况,尤其是您的情况,应该做同样的事情,因为您的 multi-module 项目设置的 Minimal, Complete, and Verifiable example 是'提供。

@Godin 的第二个解决方案为我修复了它。但除此之外,我发现 testNG 无法被 gradle 识别,因为它与 $buildDir/jacoco 下正确的 *.exec 文件不匹配。在我的例子中它是 testNg.exec,所以在我将这个块包含在我的子项目的 build.gradle:

中后它起作用了
jacocoTestReport {
  executionData testNg
}

第一个解决方案对我不起作用

task testNG(type: Test) {
  useTestNG()
  jacoco {
    destinationFile = file("$buildDir/jacoco/test.exec")
  }
}

我猜这是因为 testNG 覆盖了从 JUnit 生成的整个文件 $buildDir/jacoco/test.exec