我在单元测试日志中得到一些不一致的行为:
- 通过IntelliJ的
Run
接口运行测试 - 通过
mvn test
运行测试
当运行mvn test
时,我真的想看到以下日志语句,但是它们似乎不可见:
May 12, 2022 12:00:13 PM org.junit.jupiter.api.ClassOrderer$Random <clinit>
CONFIG: ClassOrderer.Random default seed: 155513463168987
May 12, 2022 12:00:13 PM org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter logSuccessMessage
CONFIG: Using default class orderer 'org.junit.jupiter.api.ClassOrderer$Random' set via the 'junit.jupiter.testclass.order.default' configuration parameter.
May 12, 2022 12:00:13 PM org.junit.jupiter.api.MethodOrderer$Random <clinit>
CONFIG: MethodOrderer.Random default seed: 155513483010989
Inside mypom.xml
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.config.file>
${project.build.testOutputDirectory}/logging.properties
</java.util.logging.config.file>
</systemPropertyVariables>
</configuration>
</plugin>
src/test/resources/logging.properties
目录:
.level=CONFIG
.handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=CONFIG
当通过IntelliJ的Run
接口运行测试时,我可以看到以下输出,所需的日志位于底部:
/Users/ian.jones/Library/Java/JavaVirtualMachines/openjdk-17.0.2/Contents/Home/bin/java -ea -Djava.util.logging.config.file=/Users/ian.jones/Development/my-app/target/test-classes/logging.properties -Didea.test.cyclic.buffer.size=1048576 -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=61653:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath [omitted for brevity] com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.myorg.OpenApiDocsGeneratorTest
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines
CONFIG: Discovered TestEngines with IDs: [junit-jupiter (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: 5.8.2, location: jar:file:/Users/ian.jones/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.8.2/junit-jupiter-engine-5.8.2.jar!/org/junit/jupiter/engine/JupiterTestEngine.class)]
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
CONFIG: Loaded PostDiscoveryFilter instances: []
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
CONFIG: Loaded LauncherDiscoveryListener instances: []
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
CONFIG: Loaded TestExecutionListener instances: [org.junit.platform.launcher.listeners.UniqueIdTrackingListener@2781e022]
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.LauncherConfigurationParameters loadClasspathResource
CONFIG: Loading JUnit Platform configuration parameters from classpath resource [file:/Users/ian.jones/Development/my-app/target/test-classes/junit-platform.properties].
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
CONFIG: Loaded LauncherSessionListener instances: []
May 12, 2022 12:00:13 PM org.junit.platform.launcher.core.LauncherConfigurationParameters loadClasspathResource
CONFIG: Loading JUnit Platform configuration parameters from classpath resource [file:/Users/ian.jones/Development/my-app/target/test-classes/junit-platform.properties].
May 12, 2022 12:00:13 PM org.junit.jupiter.api.ClassOrderer$Random <clinit>
CONFIG: ClassOrderer.Random default seed: 155513463168987
May 12, 2022 12:00:13 PM org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter logSuccessMessage
CONFIG: Using default class orderer 'org.junit.jupiter.api.ClassOrderer$Random' set via the 'junit.jupiter.testclass.order.default' configuration parameter.
May 12, 2022 12:00:13 PM org.junit.jupiter.api.MethodOrderer$Random <clinit>
CONFIG: MethodOrderer.Random default seed: 155513483010989
May 12, 2022 12:00:13 PM org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter logSuccessMessage
CONFIG: Using default method orderer 'org.junit.jupiter.api.MethodOrderer$Random' set via the 'junit.jupiter.testmethod.order.default' configuration parameter.
但是,当运行mvn clean install
时,对我很重要的日志没有出现:
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[ERROR] May 12, 2022 12:10:06 PM org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines
[ERROR] CONFIG: Discovered TestEngines with IDs: [junit-jupiter (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: 5.8.2, location: jar:file:/Users/ian.jones/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.8.2/junit-jupiter-engine-5.8.2.jar!/org/junit/jupiter/engine/JupiterTestEngine.class)]
[ERROR] May 12, 2022 12:10:06 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
[ERROR] CONFIG: Loaded PostDiscoveryFilter instances: []
[ERROR] May 12, 2022 12:10:06 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
[ERROR] CONFIG: Loaded LauncherDiscoveryListener instances: []
[ERROR] May 12, 2022 12:10:06 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
[ERROR] CONFIG: Loaded TestExecutionListener instances: [org.junit.platform.launcher.listeners.UniqueIdTrackingListener@76c3e77a]
[ERROR] May 12, 2022 12:10:06 PM org.junit.platform.launcher.core.LauncherConfigurationParameters loadClasspathResource
[ERROR] CONFIG: Loading JUnit Platform configuration parameters from classpath resource [file:/Users/ian.jones/Development/my-app/target/test-classes/junit-platform.properties].
[ERROR] May 12, 2022 12:10:06 PM org.junit.platform.launcher.core.ServiceLoaderRegistry load
[ERROR] CONFIG: Loaded LauncherSessionListener instances: []
[INFO] Running ...
我已经尝试将maven-surefire-plugin
的版本更改为3.0.0-M4
或3.0.0-M6
,但在这两种情况下,这会导致所有配置日志从输出中消失。
我也尝试过显式地为有问题的类设置处理程序,例如:
org.junit.jupiter.api.MethodOrderer$Random.handlers=java.util.logging.ConsoleHandler
但是,当使用Run
运行测试时,所有这些都会导致重复的输出日志行,并且在使用mvn test
运行测试时不会改变输出。
显然,它部分工作在这两种情况下,它正在阅读logging.config
(如果我删除这个文件,所有配置日志消失时运行mvn test
) -但我不知道为什么行为是不同的,或者如何修复。
编辑:最小化pom.xml
文件
这里是一个最小的pom.xml
演示问题(我使用Maven 3.8.5)
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>surefire-problem-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.config.file>
${project.build.testOutputDirectory}/logging.properties
</java.util.logging.config.file>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
简介
让我们考虑以下版本作为当前版本:
- Maven Surefire Plugin
3.0.0-M7
. - JUnit
5.8.2
.
根本原因分析
Maven Surefire Plugin使用其JUnitPlatformProvider
类。可以在«Tests»部分之前的输出中观察到:
<…>
[INFO] --- maven-surefire-plugin:3.0.0-M7:test (default-test) @ the-project ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
<…>
请参阅JUnitPlatformProvider.setupJunitLogger()
方法的实现:maven-surefire/JUnitPlatformProvider.java在surefire-3.0.0-M7·apache/maven-surefire:
private static void setupJunitLogger()
{
Logger logger = Logger.getLogger( "org.junit" );
if ( logger.getLevel() == null )
{
logger.setLevel( WARNING );
}
}
请注意条件:
logger.getLevel() == null
请参阅Logger.getLevel()
方法的文档:
public Level getLevel()
获取已为该记录器指定的日志级别。结果可能为null,这意味着该记录器的有效级别将从其父级别继承。
的回报:
this Logger's level
请注意以下语句:
结果可能为null,这意味着该记录器的有效级别将从其父级继承。
分析总结这是(参见«分析»小节)为什么:
父logger配置不被Maven Surefire Plugin考虑。
这似乎不是一个用户友好的行为。
也许,值得将其报告为Maven Surefire Plugin问题。有必要为
org.junit
包引入显式记录器配置。
解决方案有必要为org.junit
包引入显式记录器配置:
org.junit.level=CONFIG
后续:检查提供完整的pom.xml
文件
我在下列前提条件下使用了提供的完整pom.xml
文件。
我已经使用了相同的前提条件来测试解决方案。
先决条件
新增测试类
添加了3个用@TestMethodOrder(MethodOrderer.Random.class)
注释的测试类,就像这样:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(MethodOrderer.Random.class)
public class Application1Test {
@Test
public void shouldAnswerWithTrue() {
Assertions.assertTrue(true);
}
@Test
public void shouldAnswerWithTrue2() {
Assertions.assertTrue(true);
}
}
启用并行测试执行
src/test/resources/junit-platform.properties
文件内容:
junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=concurrent
新增junit相关日志级别
src/test/resources/logging.properties
:
.level=CONFIG
.handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=CONFIG
org.junit.level=CONFIG
输出$ ./mvnw clean test 2>&1 | grep -F 'MethodOrderer.Random'
CONFIG: MethodOrderer.Random default seed: 7225497639767