ããã¯ããªã«ãããããŠæžãããã®ïŒ
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ã§ã«ãã¬ããžããŒã¿ã®è¿œèšãšããŒãžãè¡ã£ãŠã¿ãŸããã
ã«ãã¬ããžããŒã¿ã®è¿œèšã¯ããã©ã«ãã®åäœã§ããããå®éã«å©çšããæã¯ãã®åäœãæŒãããŠãããæ¹ãããããã§ããã
ã«ãã¬ããžããŒã¿ã®ããŒãžã«ã€ããŠã¯ãã²ãšã€ã®ã¢ãžã¥ãŒã«ã®ã«ãã¬ããžãåå²ããŠååŸããããšã«ãªã£ãæåãã«èŠããŠããã°ããããªãšã