ããã¯ããªã«ãããããŠæžãããã®ïŒ
Maven Surefire Pluginã®includesFileã䜿ã£ãŠããã¹ãã¯ã©ã¹ãåå²ããŠå®è¡ããæ¹æ³ãèŠãŠã¿ãŸããã
Maven Surefire Pluginでテストクラスを分割してファイルで指定してみる(includesFile) - CLOVER🍀
ãã®æã«JaCoCoã§ã«ãã¬ããžãåã£ããšããããã©ãããããšã«ãªãã®ã確èªããŠã¿ãŸããã
ãé¡
䜿çšãããœãŒã¹ã³ãŒãããã³ãã¹ãã³ãŒãã¯ããã®æãšåãã«ããŸãã
Maven Surefire Pluginでテストクラスを分割してファイルで指定してみる(includesFile) - CLOVER🍀
ã€ãŸãããããããã¹ã察象ã³ãŒããš
src/main/java/org/littlewings/surefire/CalcService1.java
package org.littlewings.surefire; public class CalcService1 { public int plus(int a, int b) { return a + b; } public int minus(int a, int b) { return a - b; } }
ãããããã¹ãã³ãŒãã®ãã¢ã
src/test/java/org/littlewings/surefire/CalcService1Test.java
package org.littlewings.surefire; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; class CalcService1Test { @Test void plus() { CalcService1 sut = new CalcService1(); assertEquals(5, sut.plus(3, 2)); } @Test void minus() { CalcService1 sut = new CalcService1(); assertEquals(2, sut.minus(8, 6)); } }
10çµçšæããŸãã
$ tree src
src
âââ main
â  âââ java
â  â  âââ org
â  â  âââ littlewings
â  â  âââ surefire
â  â  âââ CalcService1.java
â  â  âââ CalcService10.java
â  â  âââ CalcService2.java
â  â  âââ CalcService3.java
â  â  âââ CalcService4.java
â  â  âââ CalcService5.java
â  â  âââ CalcService6.java
â  â  âââ CalcService7.java
â  â  âââ CalcService8.java
â  â  âââ CalcService9.java
â  âââ resources
âââ test
âââ java
âââ org
âââ littlewings
âââ surefire
âââ CalcService10Test.java
âââ CalcService1Test.java
âââ CalcService2Test.java
âââ CalcService3Test.java
âââ CalcService4Test.java
âââ CalcService5Test.java
âââ CalcService6Test.java
âââ CalcService7Test.java
âââ CalcService8Test.java
âââ CalcService9Test.java
11 directories, 20 files
ãããŠããã¹ãã³ãŒãã3ã°ã«ãŒãã«åå²ããŠããããå®è¡ããæã«ã«ãã¬ããžã¬ããŒããã©ããªãããèããŠããããšæããŸãã
# åå² $ find src/test/java -name '*.java' | perl -wp -e 's!src/test/java/!!' > test_classes.txt $ split -n 'l/3' -d test_classes.txt test_classes_group_ # ãã¹ãå®è¡ $ mvn test -Dsurefire.includesFile=test_classes_group_00 $ mvn test -Dsurefire.includesFile=test_classes_group_01 $ mvn test -Dsurefire.includesFile=test_classes_group_02
ç°å¢
ä»åã®ç°å¢ã¯ãã¡ãã
$ java --version openjdk 21.0.4 2024-07-16 OpenJDK Runtime Environment (build 21.0.4+7-Ubuntu-1ubuntu222.04) OpenJDK 64-Bit Server VM (build 21.0.4+7-Ubuntu-1ubuntu222.04, mixed mode, sharing) $ mvn --version Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 21.0.4, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-124-generic", arch: "amd64", family: "unix"
ã·ã³ãã«ã«ã«ãã¬ããžãååŸããŠã¿ã
ãŸãã¯ã·ã³ãã«ã«JaCoCoã§ã«ãã¬ããžãååŸããŠã¿ãŸãããã
JaCoCoã®Webãµã€ãã¯ãã¡ãã
EclEmma - JaCoCo Java Code Coverage Library
JaCoCo Maven Pluginã®ããã¥ã¡ã³ãã¯ãã¡ãã
ãµã³ãã«ã¯ãã¡ãã
https://www.jacoco.org/jacoco/trunk/doc/examples/build/pom.xml
ãµã³ãã«ã«ç¿ã£ãŠãã²ãšãŸãJaCoCoã®èšå®ãããŠãããŸãã
<properties> <maven.compiler.release>21</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.11.3</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.5.1</version> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.12</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
ãã¹ããå®è¡ã
$ mvn test
JaCoCoãçµã¿èŸŒãŸããŠãã¹ããå®è¡ãããŸãã
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ jacoco-surefire-tests-split-merge --- [INFO] argLine set to -javaagent:$HOME/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/path/to/target/jacoco.exec [INFO]
JaCoCoã®ã«ãã¬ããžããŒã¿ã¯ãã¡ãã§ãã
$ ll target/jacoco.exec -rw-rw-r-- 1 xxxxx xxxxx 25591 10æ 26 19:05 target/jacoco.exec
ã«ãã¬ããžã¬ããŒãäœæã
$ mvn jacoco:report
target/site/jacocoãã£ã¬ã¯ããªã«index.htmlãã§ããã®ã§ããã¡ãã確èªã

OKã§ããã
ãããŸã§ãæåã®æºåã§ãã
1床ååŸããã«ãã¬ããžã®ããŒã¿ãã¬ããŒãã¯åé€ããŠãããŸãã
$ mvn clean
ãã¹ããåå²ããŠå®è¡ããŠãã«ãã¬ããžããŒã¿ãã©ããªãã確èªããŠã¿ã
次ã«ããã¹ããåå²ããŠå®è¡ããŠã¿ãŸããããããã§ãã¹ãã®å®è¡ãé²ããŠãããšãã«ãã¬ããžã¬ããŒããã©ããªã£ãŠããã®ã確èªããŠ
ã¿ãããšæããŸãã
ãŸãã¯ãã¹ãã¯ã©ã¹ã3ã€ã®ã°ã«ãŒãã«åå²ã
$ find src/test/java -name '*.java' | perl -wp -e 's!src/test/java/!!' > test_classes.txt $ split -n 'l/3' -d test_classes.txt test_classes_group_
以äžã®3ã€ã®ãã¡ã€ã«ã«åãããŸããã
test_classes_group_00
org/littlewings/surefire/CalcService1Test.java org/littlewings/surefire/CalcService5Test.java org/littlewings/surefire/CalcService7Test.java org/littlewings/surefire/CalcService2Test.java
test_classes_group_01
org/littlewings/surefire/CalcService3Test.java org/littlewings/surefire/CalcService6Test.java org/littlewings/surefire/CalcService10Test.java
test_classes_group_02
org/littlewings/surefire/CalcService4Test.java org/littlewings/surefire/CalcService9Test.java org/littlewings/surefire/CalcService8Test.java
ãããé çªã«å®è¡ããŠãããŸãã
ãŸãã¯ã²ãšã€ãã
$ mvn test -Dsurefire.includesFile=test_classes_group_00
å®è¡ããããã¹ãã
[INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running org.littlewings.surefire.CalcService5Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.079 s -- in org.littlewings.surefire.CalcService5Test [INFO] Running org.littlewings.surefire.CalcService2Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.007 s -- in org.littlewings.surefire.CalcService2Test [INFO] Running org.littlewings.surefire.CalcService7Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.010 s -- in org.littlewings.surefire.CalcService7Test [INFO] Running org.littlewings.surefire.CalcService1Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.011 s -- in org.littlewings.surefire.CalcService1Test [INFO] [INFO] Results: [INFO] [INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0 [INFO]
ã«ãã¬ããžããŒã¿ã
$ ll target/jacoco.exec -rw-rw-r-- 1 xxxxx xxxxx 24965 10æ 26 19:06 target/jacoco.exec
ã¬ããŒããçæããŠã¿ãŸãã
$ mvn jacoco:report
åœç¶ã§ãããå®è¡ãããã¹ãã«é¢ãããã®ã®ã¿ã®ã«ãã¬ããžã«ãªã£ãŠããŸãã

ã§ã¯ããã®ç¶æ ã§æ¬¡ã®ã°ã«ãŒããå®è¡ã
$ mvn test -Dsurefire.includesFile=test_classes_group_01
å®è¡ããããã¹ãã
[INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running org.littlewings.surefire.CalcService3Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.076 s -- in org.littlewings.surefire.CalcService3Test [INFO] Running org.littlewings.surefire.CalcService6Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.007 s -- in org.littlewings.surefire.CalcService6Test [INFO] Running org.littlewings.surefire.CalcService10Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.008 s -- in org.littlewings.surefire.CalcService10Test [INFO] [INFO] Results: [INFO] [INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0 [INFO]
ã«ãã¬ããžããŒã¿ããªããã ãã¶å€§ãããªããŸãããïŒ
$ ll target/jacoco.exec -rw-rw-r-- 1 xxxxx xxxxx 49828 10æ 26 19:07 target/jacoco.exec
ã¬ããŒããäœæã
$ mvn jacoco:report
çµæã©ããªã£ãããšãããšã远èšã«ãªã£ãããã§ãã

æåŸã®ã°ã«ãŒããå®è¡ã
$ mvn test -Dsurefire.includesFile=test_classes_group_02
å®è¡ããããã¹ãã
[INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running org.littlewings.surefire.CalcService9Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.111 s -- in org.littlewings.surefire.CalcService9Test [INFO] Running org.littlewings.surefire.CalcService4Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.009 s -- in org.littlewings.surefire.CalcService4Test [INFO] Running org.littlewings.surefire.CalcService8Test [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.010 s -- in org.littlewings.surefire.CalcService8Test [INFO] [INFO] Results: [INFO] [INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0 [INFO]
JaCoCoã®ã«ãã¬ããžããŒã¿ã1åã§å šéšå®è¡ããæã®3åãããã®å€§ããã«ãªããŸãããã
$ ll target/jacoco.exec -rw-rw-r-- 1 xxxxx xxxxx 74689 10æ 26 19:07 target/jacoco.exec
ã¬ããŒããäœæãããš
$ mvn jacoco:report
å šéšæããŸãã

ãšããããã§ãã«ãã¬ããžããŒã¿ã¯è¿œèšãããããã§ãã
ãã®åäœã¯appendãšãããã©ã¡ãŒã¿ãŒã§å¶åŸ¡ãããããªã®ã§ãããããã©ã«ãå€ãæžãããŠããŸããâŠã
If set to true and the execution data file already exists, coverage data is appended to the existing file. If set to false, an existing execution data file will be replaced.
å®éã®åäœã§ç¢ºèªã§ããŠããŸãããããã©ã«ãå€ã¯trueã§ããã
appendãfalseã«èšå®ããŠã¿ã
ã§ã¯ãappendãfalseã«ãããšã©ããªãã確èªããŠã¿ãŸãã
èšå®ã以äžã®ããã«å€æŽã
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.12</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <goals> <goal>report</goal> </goals> </execution> </executions> <configuration> <append>false</append> </configuration> </plugin>
1åºŠçµæãåé€ããŠ
$ mvn clean
æåã®ã°ã«ãŒããå®è¡ããŠã«ãã¬ããžã¬ããŒãã確èªã
$ mvn test -Dsurefire.includesFile=test_classes_group_00 $ ll target/jacoco.exec -rw-rw-r-- 1 xxxxx xxxxx 24965 10æ 26 19:13 target/jacoco.exec $ mvn jacoco:report

次ã®ã°ã«ãŒããå®è¡ã
$ mvn test -Dsurefire.includesFile=test_classes_group_01 $ ll target/jacoco.exec -rw-rw-r-- 1 xxxxx xxxxx 24863 10æ 26 19:14 target/jacoco.exec $ mvn jacoco:report
jacoco.execã®ãµã€ãºãæžã£ãããšããããããããã«ãã«ãã¬ããžããŒã¿ãäžæžããããŠããŸãã

ããã§JaCoCoã®ã«ãã¬ããžããŒã¿ãããã©ã«ãã§ã¯è¿œèšã§ãç¡å¹ã«ãããšäžæžãã«ãªãããšã確èªã§ããŸãããã
ã«ãã¬ããžããŒã¿ãåå²ããŠååŸããããŒãžããŠã¿ã
ããšããšãã¡ãã®ãšã³ããªãŒãæžããã®ã¯ããã¹ãã®å®è¡ãåå²ããŠäžŠååãªã©ã§ããªãã ããããšããèæ¯ããããŸããã
Maven Surefire Pluginでテストクラスを分割してファイルで指定してみる(includesFile) - CLOVER🍀
ãªã®ã§ããã¹ãã®ã°ã«ãŒãããšã«å®è¡ãããµãŒããŒãç°ãªããªã©ãããããã§ãã
ãã®å Žåãã«ãã¬ããžããŒã¿ã¯ããããã«ååŸããŠããŒãžããããšã«ãªããŸããããã®ãããªçšéã§ã¯ãJaCoCoã®mergeãŽãŒã«ã䜿ããš
ããããã§ãã
mergeãŽãŒã«ã¯ãè€æ°ã®ããŒã¿ãã¡ã€ã«ïŒ*.execïŒãã²ãšã€ã®ãã¡ã€ã«ã«ããŒãžããŸãã
ä»åã¯ãããªèšå®ã«ããŸããã
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.12</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <destFile>${project.build.directory}/jacoco-split${test.group.index}.exec</destFile> </configuration> </execution> <execution> <id>report</id> <goals> <goal>report</goal> </goals> </execution> </executions> <configuration> <fileSets> <fileSet> <directory>${project.build.directory}</directory> <includes> <include>jacoco-split*.exec</include> </includes> </fileSet> </fileSets> </configuration> </plugin>
prepare-agentãŽãŒã«ã§ã¯ããã¹ãå®è¡æã®ã«ãã¬ããžããŒã¿ã¯${project.build.directory}/jacoco-split${test.group.index}.exec
ãšãããã¡ã€ã«ã«åºåããããã«å€æŽããŠããŸãã
<execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <destFile>${project.build.directory}/jacoco-split${test.group.index}.exec</destFile> </configuration> </execution>
${test.group.index}ãšããã®ã¯ãèªåã§è¿œå ããããããã£ã§ããå®è¡ãããã¹ãã®ã°ã«ãŒããšåãã€ã³ããã¯ã¹ãæå®ããã€ã¡ãŒãžã§ãã
<properties> ... <test.group.index></test.group.index> </properties>
mergeãŽãŒã«åãã«ãããŒãžå¯Ÿè±¡ãèšå®ã
<configuration> <fileSets> <fileSet> <directory>${project.build.directory}</directory> <includes> <include>jacoco-split*.exec</include> </includes> </fileSet> </fileSets> </configuration>
destFileãprepare-agentã®ã¿ã«æå®ããŠããã®ã§ãmergeãŽãŒã«ã§ã¯ã«ãã¬ããžããŒã¿ã¯ããã©ã«ãã®jacoco.execãšããŠåºåãããŸãã
ã¡ãªã¿ã«ãfileSetsãgoalãmergeã«èšå®ããexecutionãšconfigurationã®äžã«è¿œå ããŠãèªèããŠãããŸããã§ããâŠã
ãšããããã§ãåã°ã«ãŒãã®ãã¹ããå®è¡ã
$ mvn test -Dsurefire.includesFile=test_classes_group_00 -Dtest.group.index=0 $ mvn test -Dsurefire.includesFile=test_classes_group_01 -Dtest.group.index=1 $ mvn test -Dsurefire.includesFile=test_classes_group_02 -Dtest.group.index=2
ããããã®ã«ãã¬ããžããŒã¿ã®åºåå
ããdestFileãšããããã£ã§æå®ããå€ã«ãªã£ãŠããããšãããããŸãã
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ jacoco-surefire-tests-split-merge --- [INFO] argLine set to -javaagent:$HOME/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/path/to/target/jacoco-split0.exec [INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ jacoco-surefire-tests-split-merge --- [INFO] argLine set to -javaagent:$HOME/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/path/to/target/jacoco-split1.exec [INFO] [INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ jacoco-surefire-tests-split-merge --- [INFO] argLine set to -javaagent:$HOME/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/path/to/target/jacoco-split2.exec [INFO]
åºåãããã«ãã¬ããžããŒã¿ã
$ ll target/jacoco-split* -rw-rw-r-- 1 xxxxx xxxxx 24965 10æ 26 19:42 target/jacoco-split0.exec -rw-rw-r-- 1 xxxxx xxxxx 24863 10æ 26 19:43 target/jacoco-split1.exec -rw-rw-r-- 1 xxxxx xxxxx 24861 10æ 26 19:43 target/jacoco-split2.exec
ã¡ãªã¿ã«ããã®æç¹ã§ã¯ã¬ããŒããäœæããããšããŠã
$ mvn jacoco:report
ã«ãã¬ããžããŒã¿ãèªèããŸããã
[INFO] --- jacoco:0.8.12:report (default-cli) @ jacoco-surefire-tests-split-merge --- [INFO] Skipping JaCoCo execution due to missing execution data file.
reportãŽãŒã«ãèªã¿åãã«ãã¬ããžããŒã¿ãã¡ã€ã«ã¯dataFileã§æå®ããŸããããã®ããã©ã«ããjacoco.execã ããã§ããã
ã§ã¯ãã«ãã¬ããžããŒã¿ãããŒãžããŠã¿ãŸãã
$ mvn jacoco:merge
ãã®ããã«ããŒãžãããããã§ãã
[INFO] --- jacoco:0.8.12:merge (default-cli) @ jacoco-surefire-tests-split-merge --- [INFO] Loading execution data file /path/to/target/jacoco-split1.exec [INFO] Loading execution data file /path/to/target/jacoco-split0.exec [INFO] Loading execution data file /path/to/target/jacoco-split2.exec [INFO] Writing merged execution data to /path/to/target/jacoco.exec
ã«ãã¬ããžã¬ããŒããåºåããŠã¿ãŸãã
$ mvn jacoco:report
ããŒãžãããã«ãã¬ããžããŒã¿ãèªèããŠ
[INFO] --- jacoco:0.8.12:report (default-cli) @ jacoco-surefire-tests-split-merge --- [INFO] Loading execution data file /path/to/target/jacoco.exec [INFO] Analyzed bundle 'jacoco-surefire-tests-split-merge' with 10 classes
ç¡äºãããŒãžãããã¬ããŒãã«ãªããŸããã

ã¡ãªã¿ã«ããããªæãã§åã ã®ã«ãã¬ããžããŒã¿ãæå®ãããšããã®åäœã®ã«ãã¬ããžã¬ããŒããäœæããããšã¯ã§ããŸãã
$ mvn jacoco:report -Djacoco.dataFile=target/jacoco-split0.exec
ãããã«
JaCoCoã§ã«ãã¬ããžããŒã¿ã®è¿œèšãšããŒãžãè¡ã£ãŠã¿ãŸããã
ã«ãã¬ããžããŒã¿ã®è¿œèšã¯ããã©ã«ãã®åäœã§ããããå®éã«å©çšããæã¯ãã®åäœãæŒãããŠãããæ¹ãããããã§ããã
ã«ãã¬ããžããŒã¿ã®ããŒãžã«ã€ããŠã¯ãã²ãšã€ã®ã¢ãžã¥ãŒã«ã®ã«ãã¬ããžãåå²ããŠååŸããããšã«ãªã£ãæåãã«èŠããŠããã°ããããªãšã