0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JUnit 4のRunListenerを試す

Posted at

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"

確認用のテストを書く

最初に確認用のテストコードを用意しましょう。

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>
    </dependencies>
</project>
src/test/java/com/example/CalcTest.java
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!!");
    }
}
src/test/java/com/example/MessageTest.java
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クラスを継承したクラスを作成します。

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>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>
src/main/java/com/example/junit/MyRunListener.java
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);
    }
}
src/main/java/com/example/junit/MyRunListener2.java
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を以下のように変更。

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] ------------------------------------------------------------------------

あっさり動きましたが、雰囲気はなんとなくわかりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?