What's?
JUnit 4にはRunListenerというテスト中に発生したイベントの通知を受け取る機能があるようです。
こちらを試してみます。
RunListener
RunListenerクラスではRunNotifierクラスのインスタンスに登録することで、テスト中に発生したイベントを受け取ることができます。
RunListenerクラスに定義されているメソッドはすべて空の実装であり、必要に応じてオーバーライドします。
Register an instance of this class with RunNotifier to be notified of events that occur during a test run. All of the methods in this class are abstract and have no implementation; override one or more methods to receive events.
RunListenerクラスに定義されているメソッドは以下です。呼び出されるタイミングも書いています。
- testAssumptionFailure … アトミックテストが
falseの条件を想定している時 - testFailure … アトミックテストが失敗した時、またはリスナーが例外をスローした時
- testFinished … 成功/失敗に関係なく、アトミックテストが終了した時
- testIgnored … テストが無視対象(
@Ignore)であり実行されない時 - testRunFinished … すべてのテストが終了した時
- testRunStarted … テストが実行される前
- testStarted … アトミックテストが開始される直前
- testSuiteFinished … 成功/失敗に関係なく、テストスイートが終了した時
- testSuiteStarted … テストスイートが開始される直前
アトミックテスト???と思うのですが、どうやらテストの最小単位(テストメソッド)のことのようです。
RunNotifierクラスのインスタンスに登録して使うようですが、実際にはApache Mavenで使うことが多いでしょう。
Maven Surefire Pluginでは以下に説明があります。
Using JUnit / Using Custom Listeners and Reporters
<dependencies>
[...]
<dependency>
<groupId>your-junit-listener-artifact-groupid</groupId>
<artifactId>your-junit-listener-artifact-artifactid</artifactId>
<version>your-junit-listener-artifact-version</version>
<scope>test</scope>
</dependency>
[...]
</dependencies>
[...]
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>com.mycompany.MyResultListener,com.mycompany.MyResultListener2</value>
</property>
</properties>
</configuration>
</plugin>
[...]
</plugins>
実装したRunListenerクラスは、testスコープの依存関係として加えるか、src/test/javaにテストコードとして作成すればよいみたいです。
You can implement JUnit listener interface org.junit.runner.notification.RunListener in a separate test artifact your-junit-listener-artifact with scope=test, or in project test source code src/test/java.
なお、Gradleではサポートしていないみたいです。
簡単に試してみます。
環境
今回の環境はこちらです。
$ java -version
openjdk version "1.8.0_472"
OpenJDK Runtime Environment (build 1.8.0_472-8u472-ga-1~24.04-b08)
OpenJDK 64-Bit Server VM (build 25.472-b08, mixed mode)
$ mvn --version
Apache Maven 3.9.11 (3e54c93a704957b63ee3494413a2b544fd3d825b)
Maven home: /home/charon/.sdkman/candidates/maven/current
Java version: 1.8.0_472, vendor: Private Build, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-88-generic", arch: "amd64", family: "unix"
確認用のテストを書く
最初に確認用のテストコードを用意しましょう。
<?xml version="1.0" encoding="UTF-8"?>
<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>com.example</groupId>
<artifactId>test-example</artifactId>
<version>0.0.1</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package com.example;
import org.junit.Assert;
import org.junit.Test;
public class CalcTest {
@Test
public void plus() {
System.out.printf("%s:%s execute%n", getClass().getSimpleName(), "plus");
Assert.assertEquals(3, 1 + 2);
}
@Test
public void minus() {
System.out.printf("%s:%s execute%n", getClass().getSimpleName(), "minus");
Assert.assertEquals(5, 8 - 3);
}
@Test
public void multiply() {
System.out.printf("%s:%s execute%n", getClass().getSimpleName(), "multiply");
Assert.assertEquals(9, 3 * 2);
}
@Test
public void divide() {
System.out.printf("%s:%s execute%n", getClass().getSimpleName(), "divide");
throw new RuntimeException("Oops!!");
}
}
package com.example;
import org.junit.Assert;
import org.junit.Test;
public class MessageTest {
@Test
public void message1() {
System.out.printf("%s:%s execute%n", getClass().getSimpleName(), "message1");
Assert.assertEquals("Hello World", "Hello" + " " + "World");
}
@Test
public void message2() {
System.out.printf("%s:%s execute%n", getClass().getSimpleName(), "message2");
Assert.assertEquals("Hello World", "Hello" + " " + "World");
}
}
いくつか明らかに失敗するテストを含めています。
確認。
$ mvn test
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.MessageTest
MessageTest:message1 execute
MessageTest:message2 execute
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.031 s -- in com.example.MessageTest
[INFO] Running com.example.CalcTest
CalcTest:divide execute
CalcTest:plus execute
CalcTest:minus execute
CalcTest:multiply execute
[ERROR] Tests run: 4, Failures: 1, Errors: 1, Skipped: 0, Time elapsed: 0.001 s <<< FAILURE! -- in com.example.CalcTest
[ERROR] com.example.CalcTest.divide -- Time elapsed: 0 s <<< ERROR!
java.lang.RuntimeException: Oops!!
at com.example.CalcTest.divide(CalcTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
[ERROR] com.example.CalcTest.multiply -- Time elapsed: 0 s <<< FAILURE!
java.lang.AssertionError: expected:<9> but was:<6>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:647)
at org.junit.Assert.assertEquals(Assert.java:633)
at com.example.CalcTest.multiply(CalcTest.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
[INFO]
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] CalcTest.multiply:22 expected:<9> but was:<6>
[ERROR] Errors:
[ERROR] CalcTest.divide:28 Runtime Oops!!
[INFO]
[ERROR] Tests run: 6, Failures: 1, Errors: 1, Skipped: 0
これで準備完了としましょう。
RunListenerを作成する
では、RunListenerクラスを継承したクラスを作成します。
<?xml version="1.0" encoding="UTF-8"?>
<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>com.example</groupId>
<artifactId>my-listener</artifactId>
<version>0.0.1</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package com.example.junit;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
public class MyRunListener extends RunListener {
@Override
public void testRunStarted(Description description) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testRunStarted", description);
}
@Override
public void testRunFinished(Result result) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testRunFinished", result);
}
@Override
public void testSuiteStarted(Description description) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testSuiteStarted", description);
}
@Override
public void testSuiteFinished(Description description) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testSuiteFinished", description);
}
@Override
public void testStarted(Description description) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testStarted", description);
}
@Override
public void testFinished(Description description) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testFinished", description);
}
@Override
public void testFailure(Failure failure) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testFailure", failure);
}
@Override
public void testAssumptionFailure(Failure failure) {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testAssumptionFailure", failure);
}
@Override
public void testIgnored(Description description) throws Exception {
System.out.printf("===== %s#%s : %s%n", getClass().getSimpleName(), "testIgnored", description);
}
}
package com.example.junit;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
public class MyRunListener2 extends RunListener {
@Override
public void testRunStarted(Description description) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testRunStarted", description);
}
@Override
public void testRunFinished(Result result) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testRunFinished", result);
}
@Override
public void testSuiteStarted(Description description) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testSuiteStarted", description);
}
@Override
public void testSuiteFinished(Description description) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testSuiteFinished", description);
}
@Override
public void testStarted(Description description) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testStarted", description);
}
@Override
public void testFinished(Description description) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testFinished", description);
}
@Override
public void testFailure(Failure failure) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testFailure", failure);
}
@Override
public void testAssumptionFailure(Failure failure) {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testAssumptionFailure", failure);
}
@Override
public void testIgnored(Description description) throws Exception {
System.out.printf("***** %s#%s : %s%n", getClass().getSimpleName(), "testIgnored", description);
}
}
ログ出力だけ行うRunListenerです。クラス名も出力していますが、表示内容でも見分けられるようにしておきました。
mvn installしておきます。
$ mvn install
RunListenerを使ってみる
それでは、RunListenerを使ってみます。
pom.xmlを以下のように変更。
<?xml version="1.0" encoding="UTF-8"?>
<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>com.example</groupId>
<artifactId>test-example</artifactId>
<version>0.0.1</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>my-listener</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>org.example.junit.MyRunListener</value>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn installした、RunListenerを含むライブラリを追加。
<dependency>
<groupId>org.example</groupId>
<artifactId>my-listener</artifactId>
<version>0.0.1</version>
<scope>test</scope>
</dependency>
Maven Surefire Pluginを追加し、以下のように作成したRunListenerを設定します。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>org.example.junit.MyRunListener</value>
</property>
</properties>
</configuration>
</plugin>
テストを実行。
$ mvn test
結果はこのようになりました。
[INFO] --- surefire:3.5.4:test (default-test) @ test-example ---
[INFO] Using auto detected provider org.apache.maven.surefire.junit4.JUnit4Provider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
===== MyRunListener#testRunStarted : null
[INFO] Running com.example.MessageTest
===== MyRunListener#testSuiteStarted : com.example.MessageTest
===== MyRunListener#testStarted : message1(com.example.MessageTest)
MessageTest:message1 execute
===== MyRunListener#testFinished : message1(com.example.MessageTest)
===== MyRunListener#testStarted : message2(com.example.MessageTest)
MessageTest:message2 execute
===== MyRunListener#testFinished : message2(com.example.MessageTest)
===== MyRunListener#testSuiteFinished : com.example.MessageTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s -- in com.example.MessageTest
[INFO] Running com.example.CalcTest
===== MyRunListener#testSuiteStarted : com.example.CalcTest
===== MyRunListener#testStarted : divide(com.example.CalcTest)
CalcTest:divide execute
===== MyRunListener#testFailure : divide(com.example.CalcTest): Oops!!
===== MyRunListener#testFinished : divide(com.example.CalcTest)
===== MyRunListener#testStarted : plus(com.example.CalcTest)
CalcTest:plus execute
===== MyRunListener#testFinished : plus(com.example.CalcTest)
===== MyRunListener#testStarted : minus(com.example.CalcTest)
CalcTest:minus execute
===== MyRunListener#testFinished : minus(com.example.CalcTest)
===== MyRunListener#testStarted : multiply(com.example.CalcTest)
CalcTest:multiply execute
===== MyRunListener#testFailure : multiply(com.example.CalcTest): expected:<9> but was:<6>
===== MyRunListener#testFinished : multiply(com.example.CalcTest)
===== MyRunListener#testSuiteFinished : com.example.CalcTest
[ERROR] Tests run: 4, Failures: 1, Errors: 1, Skipped: 0, Time elapsed: 0.003 s <<< FAILURE! -- in com.example.CalcTest
[ERROR] com.example.CalcTest.divide -- Time elapsed: 0 s <<< ERROR!
java.lang.RuntimeException: Oops!!
at com.example.CalcTest.divide(CalcTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
[ERROR] com.example.CalcTest.multiply -- Time elapsed: 0 s <<< FAILURE!
java.lang.AssertionError: expected:<9> but was:<6>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:647)
at org.junit.Assert.assertEquals(Assert.java:633)
at com.example.CalcTest.multiply(CalcTest.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
===== MyRunListener#testRunFinished : org.junit.runner.Result@38082d64
[INFO]
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] CalcTest.multiply:22 expected:<9> but was:<6>
[ERROR] Errors:
[ERROR] CalcTest.divide:28 Runtime Oops!!
[INFO]
[ERROR] Tests run: 6, Failures: 1, Errors: 1, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.742 s
[INFO] Finished at: 2025-12-12T23:36:43+09:00
[INFO] ------------------------------------------------------------------------
動いているようです。
こう見ると、アトミックテストと呼ばれた範囲がわかりそうです。
===== MyRunListener#testRunStarted : null
[INFO] Running com.example.MessageTest
===== MyRunListener#testSuiteStarted : com.example.MessageTest
===== MyRunListener#testStarted : message1(com.example.MessageTest)
MessageTest:message1 execute
===== MyRunListener#testFinished : message1(com.example.MessageTest)
===== MyRunListener#testStarted : message2(com.example.MessageTest)
MessageTest:message2 execute
===== MyRunListener#testFinished : message2(com.example.MessageTest)
===== MyRunListener#testSuiteFinished : com.example.MessageTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s -- in com.example.MessageTest
[INFO] Running com.example.CalcTest
===== MyRunListener#testSuiteStarted : com.example.CalcTest
===== MyRunListener#testStarted : divide(com.example.CalcTest)
CalcTest:divide execute
===== MyRunListener#testFailure : divide(com.example.CalcTest): Oops!!
===== MyRunListener#testFinished : divide(com.example.CalcTest)
===== MyRunListener#testStarted : plus(com.example.CalcTest)
CalcTest:plus execute
===== MyRunListener#testFinished : plus(com.example.CalcTest)
===== MyRunListener#testStarted : minus(com.example.CalcTest)
CalcTest:minus execute
===== MyRunListener#testFinished : minus(com.example.CalcTest)
===== MyRunListener#testStarted : multiply(com.example.CalcTest)
CalcTest:multiply execute
===== MyRunListener#testFailure : multiply(com.example.CalcTest): expected:<9> but was:<6>
===== MyRunListener#testFinished : multiply(com.example.CalcTest)
===== MyRunListener#testSuiteFinished : com.example.CalcTest
では、RunListenerをもうひとつ追加してみましょう。複数のRunListenerを設定する場合は、カンマ区切りにすればよいみたいです。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>org.example.junit.MyRunListener,org.example.junit.MyRunListener2</value>
</property>
</properties>
</configuration>
</plugin>
テストを実行。
$ mvn test
結果。
[INFO] --- surefire:3.5.4:test (default-test) @ test-example ---
[INFO] Using auto detected provider org.apache.maven.surefire.junit4.JUnit4Provider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
===== MyRunListener#testRunStarted : null
***** MyRunListener2#testRunStarted : null
[INFO] Running com.example.MessageTest
===== MyRunListener#testSuiteStarted : com.example.MessageTest
***** MyRunListener2#testSuiteStarted : com.example.MessageTest
===== MyRunListener#testStarted : message1(com.example.MessageTest)
***** MyRunListener2#testStarted : message1(com.example.MessageTest)
MessageTest:message1 execute
===== MyRunListener#testFinished : message1(com.example.MessageTest)
***** MyRunListener2#testFinished : message1(com.example.MessageTest)
===== MyRunListener#testStarted : message2(com.example.MessageTest)
***** MyRunListener2#testStarted : message2(com.example.MessageTest)
MessageTest:message2 execute
===== MyRunListener#testFinished : message2(com.example.MessageTest)
***** MyRunListener2#testFinished : message2(com.example.MessageTest)
===== MyRunListener#testSuiteFinished : com.example.MessageTest
***** MyRunListener2#testSuiteFinished : com.example.MessageTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.039 s -- in com.example.MessageTest
[INFO] Running com.example.CalcTest
===== MyRunListener#testSuiteStarted : com.example.CalcTest
***** MyRunListener2#testSuiteStarted : com.example.CalcTest
===== MyRunListener#testStarted : divide(com.example.CalcTest)
***** MyRunListener2#testStarted : divide(com.example.CalcTest)
CalcTest:divide execute
===== MyRunListener#testFailure : divide(com.example.CalcTest): Oops!!
***** MyRunListener2#testFailure : divide(com.example.CalcTest): Oops!!
===== MyRunListener#testFinished : divide(com.example.CalcTest)
***** MyRunListener2#testFinished : divide(com.example.CalcTest)
===== MyRunListener#testStarted : plus(com.example.CalcTest)
***** MyRunListener2#testStarted : plus(com.example.CalcTest)
CalcTest:plus execute
===== MyRunListener#testFinished : plus(com.example.CalcTest)
***** MyRunListener2#testFinished : plus(com.example.CalcTest)
===== MyRunListener#testStarted : minus(com.example.CalcTest)
***** MyRunListener2#testStarted : minus(com.example.CalcTest)
CalcTest:minus execute
===== MyRunListener#testFinished : minus(com.example.CalcTest)
***** MyRunListener2#testFinished : minus(com.example.CalcTest)
===== MyRunListener#testStarted : multiply(com.example.CalcTest)
***** MyRunListener2#testStarted : multiply(com.example.CalcTest)
CalcTest:multiply execute
===== MyRunListener#testFailure : multiply(com.example.CalcTest): expected:<9> but was:<6>
***** MyRunListener2#testFailure : multiply(com.example.CalcTest): expected:<9> but was:<6>
===== MyRunListener#testFinished : multiply(com.example.CalcTest)
***** MyRunListener2#testFinished : multiply(com.example.CalcTest)
===== MyRunListener#testSuiteFinished : com.example.CalcTest
***** MyRunListener2#testSuiteFinished : com.example.CalcTest
[ERROR] Tests run: 4, Failures: 1, Errors: 1, Skipped: 0, Time elapsed: 0.003 s <<< FAILURE! -- in com.example.CalcTest
[ERROR] com.example.CalcTest.divide -- Time elapsed: 0 s <<< ERROR!
java.lang.RuntimeException: Oops!!
at com.example.CalcTest.divide(CalcTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
[ERROR] com.example.CalcTest.multiply -- Time elapsed: 0.001 s <<< FAILURE!
java.lang.AssertionError: expected:<9> but was:<6>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:647)
at org.junit.Assert.assertEquals(Assert.java:633)
at com.example.CalcTest.multiply(CalcTest.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
===== MyRunListener#testRunFinished : org.junit.runner.Result@42d3bd8b
***** MyRunListener2#testRunFinished : org.junit.runner.Result@42d3bd8b
[INFO]
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] CalcTest.multiply:22 expected:<9> but was:<6>
[ERROR] Errors:
[ERROR] CalcTest.divide:28 Runtime Oops!!
[INFO]
[ERROR] Tests run: 6, Failures: 1, Errors: 1, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.791 s
[INFO] Finished at: 2025-12-12T23:38:00+09:00
[INFO] ------------------------------------------------------------------------
あっさり動きましたが、雰囲気はなんとなくわかりました。