Jacoco + JUnit 5.0 DynamicTest 不工作
Jacoco + JUnit 5.0 DynamicTest not working
我正在尝试使用 Jacoco 与 JUnit 5 和 Spring Boot 生成代码覆盖率报告。我正在尝试使用 JUnit 5 的 DynamicTest 功能。它运行成功,但动态测试未包含在 jacoco 生成的测试覆盖率报告中。Jacoco 目前是否未包含 JUnit 5 动态测试?
代码如下:
@RunWith(JUnitPlatform.class)
@SelectPackages("com.troll.jpt.abc.model")
@SelectClasses({Status.class})
public class DynamicModelTester {
private Status status;
@BeforeEach
public void setUp() {
status = new Status();
}
@TestFactory
public Stream<DynamicTest> checkDynamicTestsFromStream() {
List<String> input = Arrays.asList("abc");
List<String> output = Arrays.asList("abc");
status.setCode(input.get(0));
return input.stream().map(str -> DynamicTest.dynamicTest("status test", () -> {
assertEquals(output.get(0), status.getCode());
}));
}
}
我使用的 jacoco 插件如下:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2-SNAPSHOT</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<dataFile>target/jacoco.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
It runs successfully but the Dynamic Tests are not covered in the test coverage report generated by jacoco.
jacoco-maven-plugin:report
不显示测试覆盖率,它显示测试目标的覆盖率 - 在您的情况下目标似乎是 class Status
,其定义完全缺席的。对于未来,我强烈建议阅读 https://whosebug.com/help/mcve 并遵循其建议,尤其是关于 "Complete":
的部分
Make sure all information necessary to reproduce the problem is included
关于 "does JaCoCo support JUnit 5 Dynamic Test?" 等问题的一般答案是:JaCoCo 记录了代码的执行方式独立于其执行方式的事实 - 通过 JUnit 4 或 JUnit 5,甚至手动或其他任何执行方式。
关于 "why some code is not marked as covered?" 等问题的一般答案是:确保代码实际执行,在自动测试的情况下,这意味着 - make确保这些测试实际执行.
但让我们尝试一下 JUnit 5 动态测试。在没有 src/main/java/Status.java
的情况下,我假设它类似于
public class Status {
private String code;
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
不知道为什么需要 systemPropertyVariables
、jacoco-maven-plugin
的快照版本、report
的多次执行以及 dataFile
的冗余规范及其默认值,所以也会假设经过轻微清理后完成 pom.xml
看起来像
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.1</version>
<configuration>
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
放置后
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
@RunWith(JUnitPlatform.class)
@SelectPackages("com.troll.jpt.abc.model")
@SelectClasses({Status.class})
public class DynamicModelTester {
private Status status;
@BeforeEach
public void setUp() {
status = new Status();
}
@TestFactory
public Stream<DynamicTest> dynamicTestsFromStream() {
List<String> input = Arrays.asList("abc");
List<String> output = Arrays.asList("abc");
status.setCode(input.get(0));
return input.stream().map(str -> DynamicTest.dynamicTest("status test", () -> {
assertEquals(output.get(0), status.getCode());
}));
}
}
进入src/test/java/DynamicModelTester.java
并执行mvn clean verify
:
[INFO] --- maven-surefire-plugin:2.21.0:test (default-test) @ example ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ example ---
[INFO] Building jar: /private/tmp/jacoco/target/example-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.1:report (default) @ example ---
[INFO] Skipping JaCoCo execution due to missing execution data file.
最后一行非常可疑,缺少 maven-surefire-plugin
执行的测试数量以及缺少 target/surefire-reports/
.
让我们把DynamicModelTester
重命名为DynamicModelTest
并再次执行mvn clean verify
:
[INFO] --- maven-surefire-plugin:2.21.0:test (default-test) @ example ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running DynamicModelTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.023 s - in DynamicModelTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ example ---
[INFO] Building jar: /private/tmp/jacoco/target/example-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.1:report (default) @ example ---
[INFO] Loading execution data file /private/tmp/jacoco/target/jacoco.exec
[INFO] Analyzed bundle 'example' with 1 classes
与之前的尝试相比,这次执行了测试。覆盖率报告 target/jacoco-ut/default/Status.html
看起来像:
我认为没有执行测试的原因在于default value of includes
of maven-surefire-plugin
:
A list of elements specifying the tests (by pattern) that
should be included in testing. When not specified and when the test
parameter is not specified, the default includes will be
<includes>
<include>**/Test*.java</include>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
<include>**/*TestCase.java</include>
</includes>
DynamicModelTester.java
不匹配这些模式中的任何一个,而 DynamicModelTest.java
匹配第二个模式,但我将验证这一点作为一个小练习。
我正在尝试使用 Jacoco 与 JUnit 5 和 Spring Boot 生成代码覆盖率报告。我正在尝试使用 JUnit 5 的 DynamicTest 功能。它运行成功,但动态测试未包含在 jacoco 生成的测试覆盖率报告中。Jacoco 目前是否未包含 JUnit 5 动态测试?
代码如下:
@RunWith(JUnitPlatform.class)
@SelectPackages("com.troll.jpt.abc.model")
@SelectClasses({Status.class})
public class DynamicModelTester {
private Status status;
@BeforeEach
public void setUp() {
status = new Status();
}
@TestFactory
public Stream<DynamicTest> checkDynamicTestsFromStream() {
List<String> input = Arrays.asList("abc");
List<String> output = Arrays.asList("abc");
status.setCode(input.get(0));
return input.stream().map(str -> DynamicTest.dynamicTest("status test", () -> {
assertEquals(output.get(0), status.getCode());
}));
}
}
我使用的 jacoco 插件如下:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2-SNAPSHOT</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<dataFile>target/jacoco.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
It runs successfully but the Dynamic Tests are not covered in the test coverage report generated by jacoco.
jacoco-maven-plugin:report
不显示测试覆盖率,它显示测试目标的覆盖率 - 在您的情况下目标似乎是 class Status
,其定义完全缺席的。对于未来,我强烈建议阅读 https://whosebug.com/help/mcve 并遵循其建议,尤其是关于 "Complete":
Make sure all information necessary to reproduce the problem is included
关于 "does JaCoCo support JUnit 5 Dynamic Test?" 等问题的一般答案是:JaCoCo 记录了代码的执行方式独立于其执行方式的事实 - 通过 JUnit 4 或 JUnit 5,甚至手动或其他任何执行方式。
关于 "why some code is not marked as covered?" 等问题的一般答案是:确保代码实际执行,在自动测试的情况下,这意味着 - make确保这些测试实际执行.
但让我们尝试一下 JUnit 5 动态测试。在没有 src/main/java/Status.java
的情况下,我假设它类似于
public class Status {
private String code;
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
不知道为什么需要 systemPropertyVariables
、jacoco-maven-plugin
的快照版本、report
的多次执行以及 dataFile
的冗余规范及其默认值,所以也会假设经过轻微清理后完成 pom.xml
看起来像
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.1</version>
<configuration>
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
放置后
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
@RunWith(JUnitPlatform.class)
@SelectPackages("com.troll.jpt.abc.model")
@SelectClasses({Status.class})
public class DynamicModelTester {
private Status status;
@BeforeEach
public void setUp() {
status = new Status();
}
@TestFactory
public Stream<DynamicTest> dynamicTestsFromStream() {
List<String> input = Arrays.asList("abc");
List<String> output = Arrays.asList("abc");
status.setCode(input.get(0));
return input.stream().map(str -> DynamicTest.dynamicTest("status test", () -> {
assertEquals(output.get(0), status.getCode());
}));
}
}
进入src/test/java/DynamicModelTester.java
并执行mvn clean verify
:
[INFO] --- maven-surefire-plugin:2.21.0:test (default-test) @ example ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ example ---
[INFO] Building jar: /private/tmp/jacoco/target/example-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.1:report (default) @ example ---
[INFO] Skipping JaCoCo execution due to missing execution data file.
最后一行非常可疑,缺少 maven-surefire-plugin
执行的测试数量以及缺少 target/surefire-reports/
.
让我们把DynamicModelTester
重命名为DynamicModelTest
并再次执行mvn clean verify
:
[INFO] --- maven-surefire-plugin:2.21.0:test (default-test) @ example ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running DynamicModelTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.023 s - in DynamicModelTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ example ---
[INFO] Building jar: /private/tmp/jacoco/target/example-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.1:report (default) @ example ---
[INFO] Loading execution data file /private/tmp/jacoco/target/jacoco.exec
[INFO] Analyzed bundle 'example' with 1 classes
与之前的尝试相比,这次执行了测试。覆盖率报告 target/jacoco-ut/default/Status.html
看起来像:
我认为没有执行测试的原因在于default value of includes
of maven-surefire-plugin
:
A list of elements specifying the tests (by pattern) that should be included in testing. When not specified and when the test parameter is not specified, the default includes will be
<includes> <include>**/Test*.java</include> <include>**/*Test.java</include> <include>**/*Tests.java</include> <include>**/*TestCase.java</include> </includes>
DynamicModelTester.java
不匹配这些模式中的任何一个,而 DynamicModelTest.java
匹配第二个模式,但我将验证这一点作为一个小练习。