LoginSignup
5
10

More than 3 years have passed since last update.

JUnit 5 + Apache Maven による Java の自動テスト導入

Posted at

概要

  • JUnit 5 + Apache Maven による Java の自動テストについて基本的なサンプルを書く

今回の環境

  • Java 11 (AdoptOpenJDK 11.0.8+10)
  • JUnit Jupiter 5.7.0
  • Apache Maven 3.6.3
  • Maven Surefire Plugin 3.0.0-M5

JUnit 5 + Apache Maven の基本的なサンプル

ソースコード一覧

├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── myapp
    │           └── Calc.java
    └── test
        └── java
            └── myapp
                └── CalcTest.java

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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>mygroup</groupId>
  <artifactId>myapp</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0</version>
  <name>myapp</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <build>
    <plugins>
      <!-- JUnit 5 でのテスト実行に必要なプラグインを導入 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M5</version>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <!-- テストコードの記述に必要なライブラリを導入 -->
    <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.7.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

参考:

Calc.java

package myapp;

public class Calc {

  private int base;

  // 基準となる値を設定
  public Calc(int base) {
    this.base = base;
  }

  // 足す
  public int plus(int num) {
    return base + num;
  }

  // 引く
  public int minus(int num) {
    return base - num;
  }
}

CalcTest.java

package myapp;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class CalcTest {

  // テスト開始前に1回だけ実行される
  @BeforeAll
  static void beforeAll() {
    System.out.println("CalcTest 開始");
  }

  // テスト開始後に1回だけ実行される
  @AfterAll
  static void afterAll() {
    System.out.println("CalcTest 終了");
  }

  // 各テストメソッド開始前に実行される
  @BeforeEach
  void beforeEach() {
    System.out.println("CalcTest のテストメソッドをひとつ開始");
  }

  // 各テストメソッド開始後に実行される
  @AfterEach
  void afterEach() {
    System.out.println("CalcTest のテストメソッドをひとつ終了");
  }

  // テストメソッドは private や static メソッドにしてはいけない
  // 値を返してもいけないので戻り値は void にする
  @Test
  void testPlus() {
    System.out.println("testPlus を実行: 2 + 3 = 5");
    Calc calc = new Calc(2);
    // 第1引数: expected 想定される結果
    // 第2引数: actual 実行結果
    // 第3引数: message 失敗時に出力するメッセージ
    assertEquals(5, calc.plus(3), "2 + 3 = 5 の検証");
  }

  @Test
  void testMinus() {
    System.out.println("testMinus を実行: 5 - 2 = 3");
    Calc calc = new Calc(5);
    assertEquals(3, calc.minus(2), "5 - 2 = 3 の検証");
  }
}

参考:

テスト成功時の例

$ mvn test
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------------< mygroup:myapp >----------------------------
[INFO] Building myapp 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
(中略)
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ myapp ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running myapp.CalcTest
CalcTest 開始
CalcTest のテストメソッドをひとつ開始
testMinus を実行: 5 - 2 = 3
CalcTest のテストメソッドをひとつ終了
CalcTest のテストメソッドをひとつ開始
testPlus を実行: 2 + 3 = 5
CalcTest のテストメソッドをひとつ終了
CalcTest 終了
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.087 s - in myapp.CalcTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

テスト失敗時の例

$ mvn test
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------------< mygroup:myapp >----------------------------
[INFO] Building myapp 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
(中略)
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ myapp ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running myapp.CalcTest
CalcTest 開始
CalcTest のテストメソッドをひとつ開始
testMinus を実行: 5 - 2 = 3
CalcTest のテストメソッドをひとつ終了
CalcTest のテストメソッドをひとつ開始
testPlus を実行: 2 + 3 = 5
CalcTest のテストメソッドをひとつ終了
CalcTest 終了
[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.063 s <<< FAILURE! - in myapp.CalcTest
[ERROR] myapp.CalcTest.testMinus  Time elapsed: 0.026 s  <<< FAILURE!
org.opentest4j.AssertionFailedError: 5 - 2 = 3 の検証 ==> expected: <3> but was: <7>
  at myapp.CalcTest.testMinus(CalcTest.java:53)

[INFO] 
[INFO] Results:
[INFO] 
[ERROR] Failures: 
[ERROR]   CalcTest.testMinus:53 5 - 2 = 3 の検証 ==> expected: <3> but was: <7>
[INFO] 
[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

assertAll でまとめてテストするサンプル

サンプルコード

package myapp;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

class CalcTest {

  @Test
  void testPlus() {
    Calc calc = new Calc(10);
    // まとめて検証
    // 途中で失敗しても停止せずにすべて検証する
    assertAll(
     () -> assertEquals(30, calc.plus(20)),
     () -> assertEquals(99, calc.plus(90)),
     () -> assertEquals(11, calc.plus(50)),
     () -> assertEquals(40, calc.plus(30))
    );
  }
}

参考:

テスト失敗時の例

$ mvn test
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------------< mygroup:myapp >----------------------------
[INFO] Building myapp 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
(中略)
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ myapp ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running myapp.CalcTest
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.067 s <<< FAILURE! - in myapp.CalcTest
[ERROR] myapp.CalcTest.testPlus  Time elapsed: 0.044 s  <<< FAILURE!
org.opentest4j.MultipleFailuresError: 
Multiple Failures (2 failures)
  org.opentest4j.AssertionFailedError: expected: <99> but was: <100>
  org.opentest4j.AssertionFailedError: expected: <11> but was: <60>
  at myapp.CalcTest.testPlus(CalcTest.java:15)

[INFO] 
[INFO] Results:
[INFO] 
[ERROR] Failures: 
[ERROR]   CalcTest.testPlus:15 Multiple Failures (2 failures)
  org.opentest4j.AssertionFailedError: expected: <99> but was: <100>
  org.opentest4j.AssertionFailedError: expected: <11> but was: <60>
[INFO] 
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

例外発生テストのサンプル

package myapp;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

class CalcTest {

  @Test
  void testPlus() {
    Calc calc = new Calc(100);
    // 0 で割ったら ArithmeticException が発生することを想定
    ArithmeticException e =
      assertThrows(ArithmeticException.class,
        () -> calc.divide(0));
    assertTrue(e instanceof ArithmeticException);
  }
}

参考資料

5
10
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
5
10