如何用Maven在不同JVM下顺序/并行运行Surefire单元测试并聚合报告?
Great question! Running unit tests across different JVMs is a common need for ensuring cross-compatibility, and Maven gives you flexible ways to handle this—plus options to aggregate results into a single report. Let’s break this down step by step:
1. Running Tests with a Specific JVM Individually
Maven uses the JVM it’s launched with by default, but you can override this in two straightforward ways:
Option A: Temporarily Set JAVA_HOME
Before executing Maven, point JAVA_HOME to your target JVM’s installation directory. This is the simplest approach for one-off runs.
Bash Example:
# For OpenJDK HotSpot export JAVA_HOME=/opt/openjdk-hotspot mvn clean test # For Eclipse OpenJ9 export JAVA_HOME=/opt/openj9-jvm mvn clean test # For SAP JVM export JAVA_HOME=/opt/sapjvm mvn clean test # For Azul Zulu export JAVA_HOME=/opt/azul-zulu mvn clean test
Windows Command Prompt Example:
set JAVA_HOME=C:\Program Files\OpenJDK\hotspot mvn clean test
Option B: Use Maven Exec Plugin (No JAVA_HOME Change)
If you don’t want to modify your environment variables, use the exec:exec goal to call the specific JVM’s java executable directly. Add this to your pom.xml:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>run-tests-with-openj9</id> <goals><goal>exec</goal></goals> <phase>test</phase> <configuration> <!-- Replace with your JVM's java path --> <executable>/opt/openj9-jvm/bin/java</executable> <arguments> <argument>-cp</argument> <argument>${project.build.outputDirectory}:${project.build.testOutputDirectory}:${maven.test.classpath}</argument> <argument>org.junit.runner.JUnitCore</argument> <!-- Replace with your test class/package --> <argument>com.yourcompany.YourTestSuite</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build>
Run it with: mvn exec:exec@run-tests-with-openj9
2. Running Tests Sequentially Across Multiple JVMs
For repeatable sequential runs, use Maven profiles to encapsulate each JVM’s configuration. This keeps your setup clean and maintainable.
Add these profiles to your pom.xml:
<profiles> <profile> <id>hotspot</id> <properties> <jvm.path>/opt/openjdk-hotspot/bin/java</jvm.path> <report.dir>target/surefire-reports-hotspot</report.dir> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> <configuration> <reportsDirectory>${report.dir}</reportsDirectory> <forkCount>1</forkCount> <jvm>${jvm.path}</jvm> </configuration> </plugin> </plugins> </build> </profile> <!-- Repeat for OpenJ9, SAP JVM, Azul --> <profile> <id>openj9</id> <properties> <jvm.path>/opt/openj9-jvm/bin/java</jvm.path> <report.dir>target/surefire-reports-openj9</report.dir> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> <configuration> <reportsDirectory>${report.dir}</reportsDirectory> <forkCount>1</forkCount> <jvm>${jvm.path}</jvm> </configuration> </plugin> </plugins> </build> </profile> </profiles>
Run all profiles sequentially with:
mvn clean test -P hotspot,openj9,sapjvm,azul
3. Running Tests in Parallel Across Multiple JVMs
To speed things up, run tests across JVMs in parallel using a shell script that launches each Maven command in the background.
Bash Script Example (run-tests-parallel.sh):
#!/bin/bash # Define JVM paths and labels JVM_SETUPS=( "/opt/openjdk-hotspot:hotspot" "/opt/openj9-jvm:openj9" "/opt/sapjvm:sapjvm" "/opt/azul-zulu:azul" ) # Launch each test run in the background for setup in "${JVM_SETUPS[@]}"; do IFS=":" read -r java_home label <<< "$setup" export JAVA_HOME="$java_home" mvn clean test -Dsurefire.reportsDirectory=target/surefire-reports-$label & done # Wait for all background processes to finish wait echo "All parallel test runs completed successfully!"
Make it executable (chmod +x run-tests-parallel.sh) and run it.
4. Aggregating Test Results into a Single Report
Use the Maven Surefire Report Plugin to combine results from all JVM runs into one HTML report. Add this to your pom.xml:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-report-plugin</artifactId> <version>3.2.5</version> <configuration> <reportsDirectories> <reportsDirectory>target/surefire-reports-hotspot</reportsDirectory> <reportsDirectory>target/surefire-reports-openj9</reportsDirectory> <reportsDirectory>target/surefire-reports-sapjvm</reportsDirectory> <reportsDirectory>target/surefire-reports-azul</reportsDirectory> </reportsDirectories> </configuration> </plugin> </plugins> </build>
Generate the aggregated report with:
mvn surefire-report:report
The final report will be at target/site/surefire-report.html, showing all test results grouped by JVM.
内容的提问来源于stack exchange,提问作者Mahatma_Fatal_Error

