Mavenで一部のテストの実行/除外を切り替える
やりたいこと
- 一部のテストは、普段(mvn test で実行したとき)は実行されないようにする。
- ただし、mvn の引数で何かを指定すれば実行できるようにする。
- また、そのテストは、NetBeansから「ファイルのテスト」で単独実行されるようにする。
使用した環境
JUnitの@Categoryを使ってテストをグループ分け
「一部のテスト」には、JUnitの@Categoryでカテゴリを指定することで、他のテストと区別する。
Maven側では、特定のカテゴリのみテストを実行したり、テスト対象から除外したりできる。
カテゴリを指定するためには、カテゴリを表すマーカー用のクラスかインタフェースを作り、それをテストクラスに@Categoryを使って指定する。
マーカー用のインタフェースの例。インタフェース名は何でもよい。 (src/test/java 配下に置く)
package sample.maven.test; public interface ExtraTest { }
@Categoryを指定したテストクラスの例
package sample.maven; import org.junit.Test; import static org.junit.Assert.*; import org.junit.experimental.categories.Category; import sample.maven.test.ExtraTest; @Category(ExtraTest.class) public class GreeterSlowTest { @Test public void testSlowSayHello() { String actual = new Greeter().sayHello("Suzuki"); String expected = "Hello Suzuki!"; assertEquals(expected, actual); } }
普段のテストから指定のカテゴリを除外する
maven-surefire-plugin プラグインを設定して、指定のカテゴリをテスト対象から除外する。
pom.xmlにmaven-surefire-pluginの設定がなければ、暗黙の設定がどうなっているかを、mvn help:effective-pom で確認できる。mvn help:effective-pom を実行すると、pom.xmlで記述していないものも含め、現在有効になっている設定が表示される。試した環境では、maven-surefire-plugin の暗黙の設定は次のようになっていた。
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.10</version> <executions> <execution> <id>default-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin>
これを自分のpom.xmlに貼り付け、pom.xmlは次のようにした。
<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>sample</groupId> <artifactId>MavenSample</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>MavenSample</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <!-- 4.8以上が必要 --> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <!-- 2.13以上? が必要 --> <executions> <execution> <id>default-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> <configuration> <excludedGroups>sample.maven.test.ExtraTest</excludedGroups> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
ポイントは、
- surefireの設定にexcludedGroupsを追加して、除外したいカテゴリのマーカー用クラス/インタフェースを指定。
また、
以上の設定で、 mvn test を実行したときには @Category(ExtraTest.class)の付いたテストは対象から除外される。
指定のテストだけ実行するための設定
surefireプラグインは、パラメータgroupsにカテゴリのマーカー用クラス/インタフェースを指定すると、そのカテゴリだけを対象にテストを実行する。これを利用すれば所望の設定ができる。
一方、surefireプラグインは、上記の設定により、ExtraTestは除外するよう設定済みである。しかし、
executionタグを追加し既存とは異なるidを指定することにより、別の設定のsurefireプラグインを追加することが可能となる。
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <executions> <execution> <id>default-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> <configuration> <excludedGroups>sample.maven.test.ExtraTest</excludedGroups> </configuration> </execution> <!-- ここから追加 --> <execution> <id>extra-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> <configuration> <groups>sample.maven.test.ExtraTest</groups> </configuration> </execution> </executions> </plugin>
ここでは、extra-testというidでsurefireの設定を追加した。
なお、以下の指定は
<phase>test</phase> <goals> <goal>test</goal> </goals>
次のような意味になる。
surefireプラグインが提供しているゴールは"test" 1個だけであり、そのゴールはJUnitなどを使ってテストを実行する。つまり、mvn test と実行すれば、extra-testと名づけた設定でsurefireプラグインによるテストが実行される。
この設定のままだと mvn test したときには、デフォルト(id: default-test)と、追加した id: extra-test の両方が実行されてしまう。extra-testのほうは普段は実行せず、明示的に指定されたときだけ実行されるようにしたい。これは、surefireプラグインのパラメータ skipTests と、mavenのプロパティを利用して実現できる。
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <skipExtraTest>true</skipExtraTest> <!-- これを追加 --> </properties> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <executions> <execution> <id>default-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> <configuration> <excludedGroups>sample.maven.test.ExtraTest</excludedGroups> </configuration> </execution> <execution> <id>extra-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> <configuration> <skipTests>${skipExtraTest}</skipTests> <!-- これを追加 --> <groups>sample.maven.test.ExtraTest</groups> </configuration> </execution> </executions> </plugin> </plugins> </build>
surefireプラグインのskipTestsパラメータにtrueを指定すると実行はスキップされる。 skipTestsの値は、独自に追加したskipExtraTestプロパティで与えるようにして、skipExtraTestプロパティのデフォルト値はtrueにしておく(propertiesタグに追加した設定により指定している)。すなわち、デフォルトではスキップされる。
extra-testを実行したい場合は、次のようにskipExtraTestをfalseにして実行すればよい。
mvn -DskipExtraTest=false test
NetBeansからの実行
テストプログラム作成中は「ファイルをテスト」「ファイルのテストをデバッグ」を使って、作成中のテストクラスだけ実行させるのが便利だが、この場合は、@Categoryの有無にかかわらず指定のテストクラスが実行される。
どうやらこのケースの場合は、ここまでで定義したid: default-test, id: extra-testのどちらの設定も適用されていないようだ。「ファイルをテスト」の場合、NetBeansは、mvn test ではなく mvn surefire:test のように、直接ゴール(surefire:test)を指定して実行している。そしてこの場合適用される設定は id: default-test ではなくid: default-cli となるようだ。このことは、mvn surefire:test を実行したときの次の表示から推測できる。
--- maven-surefire-plugin:2.16:test (default-cli) @ MavenSample ---
なお、実行>プロジェクトをテスト の場合は、mvn test で実行されるため、id: extra-testはスキップされる。
備考
プラグインの設定記述例としてよく見かけるのは、次のようにexecutionsタグを使わずにconfigurationを書いている例だが、この場合は、暗黙に定義されているものも含め、すべてのidの設定にこの設定が追加されるようだ。
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <configuration> <excludedGroups>sample.maven.test.ExtraTest</excludedGroups> </configuration> </plugin>
このため、上記の設定であれば、NetBeansから「ファイルをテスト」を実行した場合にもExtraTestは除外される。つまり、ExtraTestをつけたテストクラスは「ファイルをテスト」では実行できなくなってしまう。