Maven/GradleでJUnitテストのもろもろ
テストに失敗した際にスタックトレースを出力させる
Maven/GradleでJUnitテストに失敗した際に出力されるログには、デフォルトではテスト側コードの失敗した1行しか出力されないようになっています。
そのためテスト対象コードのどこで失敗したのかわからないことがあります。
public class PersonService {
public String getName() {
throw new RuntimeException();
}
}
class PersonServiceTest {
@Test
void 名前を取得() {
String actual = new PersonService().getName();
assertEquals("hanako", actual);
}
}
$ mvn test
[ERROR] 名前を取得 Time elapsed: 0.035 s <<< ERROR!
java.lang.RuntimeException
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
$ ./gradlew test
PersonServiceTest > 名前を取得() FAILED
java.lang.RuntimeException at PersonServiceTest.java:10
この場合だとPersonServiceTestが失敗したことはわかりますが、PersonServiceのどの場所で失敗したのかわかりません。今回のものはシンプルなコードなので困ることも少ないと思いますが、テストクラス対象から別のクラスを呼び出して・・・となると原因を調査するのが大変になります。
そこでスタックトレースを出力できるように設定します。
Maven
-DtrimStackTrace=false
をつけてtest実行するかmaven-surefire-pluginのconfigurationにtrimStackTrace=false
を設定することでスタックトレースを全て出力することが可能です。
-DtrimStackTrace=false
の場合
$ mvn -DtrimStackTrace=false test
[ERROR] 名前を取得 Time elapsed: 0.027 s <<< ERROR!
java.lang.RuntimeException
at com.example.testdemo.PersonService.getName(PersonService.java:8)
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
--- 省略 ---
maven-surefire-pluginのconfigurationにtrimStackTrace=false
を設定する場合
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
$ mvn test
[ERROR] 名前を取得 Time elapsed: 0.026 s <<< ERROR!
java.lang.RuntimeException
at com.example.testdemo.PersonService.getName(PersonService.java:8)
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
--- 省略 ---
Gradle
testタスクのtestLoggingプロパティのexceptionFormat
プロパティにfull
を設定します。
test {
testLogging {
exceptionFormat "full"
}
}
$ ./gradlew test
PersonServiceTest > 名前を取得() FAILED
java.lang.RuntimeException
at com.example.testdemo.PersonService.getName(PersonService.java:8)
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
テストの失敗を無視する
テストに失敗してもビルドなどをしたい場合の方法です。
具体的な利用イメージとしてはテストコードがメンテされずに、CIを導入時に大量のエラーが出て困るみたいなケースが想定されます。
Maven
-Dmaven.test.failure.ignore=true
をつけてtest実行をするか、maven-surefire-pluginのconfigurationにtestFailureIgnore=true
を設定ことでスタックトレースを全て出力することが可能です。
-Dmaven.test.failure.ignore=true
の場合
$ mvn -Dmaven.test.failure.ignore=true test
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.028 s <<< FAILURE! - in com.example.testdemo.PersonServiceTest
[ERROR] 名前を取得 Time elapsed: 0.022 s <<< ERROR!
java.lang.RuntimeException
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
をつけてtest実行をするか、maven-surefire-pluginのconfigurationにtestFailureIgnore=true
を設定する場合
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
$ mvn test
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.03 s <<< FAILURE! - in com.example.testdemo.PersonServiceTest
[ERROR] 名前を取得 Time elapsed: 0.023 s <<< ERROR!
java.lang.RuntimeException
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Gradle
testタスクのignoreFailures
プロパティにtrue
を設定します。
test {
testLogging {
ignoreFailures true
}
}
$ ./gradlew test
PersonServiceTest > 名前を取得() FAILED
java.lang.RuntimeException
at com.example.testdemo.PersonService.getName(PersonService.java:8)
at com.example.testdemo.PersonServiceTest.名前を取得(PersonServiceTest.java:10)
2 tests completed, 1 failed
BUILD SUCCESSFUL in 7s
参考
Maven -> surefire:test
Gradle -> Test
Gradle -> TestLoggingContainer
Discussion