CLOVER🍀

That was when it all began.

Maven Surefire Pluginのincludeになにを指定したらいいのかわからないずいう話

これは、なにをしたくお曞いたもの

Maven Surefire Pluginにはincludes  include、excludes  excludeでテストを絞り蟌んだり陀倖したりする機胜がありたす。

ドキュメントを芋おいるず、なにずマッチさせおいるのかがい぀もよくわからなくなるので調べおみたした。

Maven Surefire Pluginのincludesずexcludes

察象のドキュメントはこちら。

Maven Surefire Plugin – Inclusions and Exclusions of Tests

今回はincludes  includeを察象にしたす。

たずはシンプルな䜿い方から。サンプルはこんな感じですね。

        <configuration>
          <includes>
            <include>Sample.java</include>
          </includes>
        </configuration>

ワむルドカヌド*、**も含め、Javaの゜ヌスコヌド名で指定するように芋えたす。

  • "**/Test*.java" - includes all of its subdirectories and all Java filenames that start with "Test".
  • "**/*Test.java" - includes all of its subdirectories and all Java filenames that end with "Test".
  • "**/*Tests.java" - includes all of its subdirectories and all Java filenames that end with "Tests".
  • "**/*TestCase.java" - includes all of its subdirectories and all Java filenames that end with "TestCase".

Inclusions and Exclusions of Tests / Inclusions

%regex[.*(Cat|Dog).*Test.*]のように、正芏衚珟での指定もできたす。

Inclusions and Exclusions of Tests / Regular Expression Support

surefire:testのドキュメントにも同じようなこずがたずめられおいたす。

surefire:test / Parameter Details / includes

じゃあ、きっちり指定しようず思うずsrc/test/java/path/to/AbcTest.javaずか曞くんですか ずいう気になるので、Maven Surefire Pluginの
includes  includeがなにずマッチさせおいるのかちょっず芋おみたした。

ちなみに、testを䜿うずメ゜ッドレベルたで絞り蟌んだり、includes  include、excludes  excludeを䞀括で指定できたりず
さらに柔軟に扱えたす。

surefire:test / Parameter Details / test

これはincludeやexcludeにカンマ区切りで指定するこずで同じ動䜜が実珟できるようです。今回はこちらは扱いたせん。

Inclusions and Exclusions of Tests / Multiple Formats in One

たた、ここたでの話はMaven Failsafe Pluginでも同じだず思いたす。

Maven Failsafe Plugin – Inclusions and Exclusions of Tests

Maven Failsafe Plugin – failsafe:integration-test

環境

今回の環境はこちら。

$ 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.8 (36645f6c9b5079805ea5009217e36f2cffd34256)
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-117-generic", arch: "amd64", family: "unix"

準備

Maven䟝存関係など。

    <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.10.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.3.1</version>
                <configuration>
                    <!-- あずで -->
                </configuration>
            </plugin>
        </plugins>
    </build>

Maven Surefire Pluginの蚭定はあずで曞きたす。

テストコヌドを甚意する

テスト察象ずなるテストコヌドを甚意したす。

Maven Surefire Pluginの動䜜を芋るだけなので、テストの䞭身は芁りたせん。いるのはファむル名やパスのバリ゚ヌションですね。

src/test/java/org/littlewings/surefire/SampleTest.java

package org.littlewings.surefire;

import org.junit.jupiter.api.Test;

class SampleTest {
    @Test
    void test() {
    }
}

src/test/java/org/littlewings/surefire/sample/SampleTest.java

package org.littlewings.surefire.sample;

import org.junit.jupiter.api.Test;

class SampleTest {
    @Test
    void test() {
    }
}

src/test/java/org/littlewings/surefire/foo/FooTest.java

package org.littlewings.surefire.foo;

import org.junit.jupiter.api.Test;

class FooTest {
    @Test
    void test() {
    }
}

src/test/java/org/littlewings/surefire/bar/BarTest.java

package org.littlewings.surefire.bar;

import org.junit.jupiter.api.Test;

class BarTest {
    @Test
    void test() {
    }
}

src/test/java/org/littlewings/surefire/hoge/HogeTest.java

package org.littlewings.surefire.hoge;

import org.junit.jupiter.api.Test;

public class HogeTest {
    @Test
    void test() {
    }
}

Maven Surefire Pluginのincludesincludeを蚭定する

甚意したテストコヌドのパスは以䞋です。

  • src/test/java/org/littlewings/surefire/SampleTest.java
  • src/test/java/org/littlewings/surefire/sample/SampleTest.java
  • src/test/java/org/littlewings/surefire/foo/FooTest.java
  • src/test/java/org/littlewings/surefire/bar/BarTest.java
  • src/test/java/org/littlewings/surefire/hoge/HogeTest.java

たずはなにも蚭定せずにテストを動かしたす。

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.3.1</version>
                <configuration>
                </configuration>
            </plugin>

実行。

$ mvn test

圓然ですが、すべおのテストコヌドが実行されたす。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.bar.BarTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.061 s -- in org.littlewings.surefire.bar.BarTest
[INFO] Running org.littlewings.surefire.hoge.HogeTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.hoge.HogeTest
[INFO] Running org.littlewings.surefire.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.SampleTest
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.sample.SampleTest
[INFO] Running org.littlewings.surefire.foo.FooTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 s -- in org.littlewings.surefire.foo.FooTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0

SampleTest.javaず曞いおみたす。

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.3.1</version>
                <configuration>
                    <includes>
                        <include>SampleTest.java</include>
                    </includes>
                </configuration>
            </plugin>

実行。

$ mvn test

2぀のテストクラスが実行されたした。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.058 s -- in org.littlewings.surefire.SampleTest
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.sample.SampleTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

埌方䞀臎しおいるような感じですね。

こう蚭定しおみるずどうでしょうか。
※ここからはconfigurationのみを蚘茉したす

                <configuration>
                    <includes>
                        <include>**/SampleTest.java</include>
                    </includes>
                </configuration>

結果は倉わりたせん。぀たり、同じ意味だったずいうこずになるのでしょうか
※mvn testの実行も以降は省略したす

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.049 s -- in org.littlewings.surefire.SampleTest
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.sample.SampleTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

ちなみに、.javaを曞かなくおも動いたりしたす。

                <configuration>
                    <includes>
                        <include>**/SampleTest</include>
                    </includes>
                </configuration>

結果。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.054 s -- in org.littlewings.surefire.SampleTest
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.sample.SampleTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

これを芋るず、ちょっずなにを察象にしおいるかわからなくなりたすよね 。

ワむルドカヌドを䜿った䟋。

                <configuration>
                    <includes>
                        <include>**/Ba*Test.java</include>
                    </includes>
                </configuration>

結果。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.bar.BarTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.043 s -- in org.littlewings.surefire.bar.BarTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

正芏衚珟。%regex[パタヌン]で曞きたす。

                <configuration>
                    <includes>
                        <include>%regex[.*FooTest.*]</include>
                    </includes>
                </configuration>

結果。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.foo.FooTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.048 s -- in org.littlewings.surefire.foo.FooTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

前埌の.*が重芁のようで、削陀するずテスト察象にならなくなりたす。

                <configuration>
                    <includes>
                        <include>%regex[.*FooTest]</include>
                    </includes>
                </configuration>

こちらもテスト察象がれロになりたす。

                <configuration>
                    <includes>
                        <include>%regex[FooTest.*]</include>
                    </includes>
                </configuration>

最埌に組み合わせで。

                <configuration>
                    <includes>
                        <include>SampleTest.java</include>
                        <include>**/Ba*Test.java</include>
                        <include>%regex[.*FooTest.*]</include>
                    </includes>
                </configuration>

結果。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.bar.BarTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.064 s -- in org.littlewings.surefire.bar.BarTest
[INFO] Running org.littlewings.surefire.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in org.littlewings.surefire.SampleTest
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 s -- in org.littlewings.surefire.sample.SampleTest
[INFO] Running org.littlewings.surefire.foo.FooTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 s -- in org.littlewings.surefire.foo.FooTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

Maven Surefire Pluginのincludeexcludeはなにを芋おいるのか

Maven Surefire Pluginでテスト察象に含める、たたは陀倖するかを刀定しおいるのはこちらです。

https://github.com/apache/maven-surefire/blob/surefire-3.3.1/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/TestListResolver.java#L177-L205

テストが指定されたパタヌンに䞀臎すればテスト察象ずなり、たた陀倖察象にもなりたす。

            boolean shouldRun = false;

            if (getIncludedPatterns().isEmpty()) {
                shouldRun = true;
            } else {
                for (ResolvedTest filter : getIncludedPatterns()) {
                    if (filter.matchAsInclusive(testClassFile, methodName)) {
                        shouldRun = true;
                        break;
                    }
                }
            }

            if (shouldRun) {
                for (ResolvedTest filter : getExcludedPatterns()) {
                    if (filter.matchAsExclusive(testClassFile, methodName)) {
                        shouldRun = false;
                        break;
                    }
                }
            }
            return shouldRun;

マッチ察象はクラスずメ゜ッドがあるのですが、今回はメ゜ッドのみを芋たす。

クラス名は以䞋でフォヌマットされたす。

https://github.com/apache/maven-surefire/blob/surefire-3.3.1/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/ResolvedTest.java#L273-L284

この時、.javaは.classに眮き換えられたす。

https://github.com/apache/maven-surefire/blob/surefire-3.3.1/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/ResolvedTest.java#L286-L296

たた、パスの先頭が**/で始たっおいない堎合は远加されたす。

https://github.com/apache/maven-surefire/blob/surefire-3.3.1/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/ResolvedTest.java#L277-L279

぀たり、SampleTest.javaは**/SampleTest.classず同じです。

.javaずいう感じで゜ヌスコヌドを指定したのですが、結局察象にしおいるのは.classのようですね。

そしお、こちらで枡されるクラスファむルずマッチするか確認するのですが、この時に枡されるtestClassFileはorg/littlewings/surefire/SampleTest.classのような倀が枡っおきたす。

https://github.com/apache/maven-surefire/blob/surefire-3.3.1/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/TestListResolver.java#L177-L205

ずいうこずは、マッチするか刀定しおいるのはテスト察象の゜ヌスコヌドのパスではなく、テスト察象のクラスですね。

正芏衚珟を䜿った堎合は、パスの補正は入りたせん。そしお、指定された正芏衚珟に察しおorg/littlewings/surefire/SampleTest.classの
ようなクラスに察しおマッチを詊みたす。

こうなるず、前埌のパタヌンを削るずマッチしなくなった理由がわかる気がしたす。

ここたでわかるず、実は.classで指定しおもよいこずがわかりたすね。

                <configuration>
                    <includes>
                        <include>SampleTest.class</include>
                    </includes>
                </configuration>

そしお、拡匵子がなくおもよかったこずもわかりたす。

                <configuration>
                    <includes>
                        <include>SampleTest</include>
                    </includes>
                </configuration>

結果はどちらもこうなりたす。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.056 s -- in org.littlewings.surefire.SampleTest
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 s -- in org.littlewings.surefire.sample.SampleTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

オマケ的に。

                <configuration>
                    <includes>
                        <include>**/sample/*SampleTest</include>
                    </includes>
                </configuration>

結果。

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.littlewings.surefire.sample.SampleTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.056 s -- in org.littlewings.surefire.sample.SampleTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

こんなずころでしょうか。

おわりに

Maven Surefire Pluginのincludeになにを指定したらいいのかよくわかっおいなかったので、ちょっず詳しくみおみたした。

なんずなく雰囲気で指定しおいるこずが倚かったのですが、どういう挙動をしおいるかわかったのでどう曞くずどういう結果になるかが
だいぶわかるようになった気がしたす。