LoginSignup
15
22

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-21

概要

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

Junit 5 とは

  • JUnit は Java の自動テスト用フレームワーク
  • JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
  • JUnit Platform: テスト実行プラットフォーム
  • JUnit Jupiter: テストコード実装用APIとテストエンジンを提供
  • JUnit Vintage: JUnit 3 と JUnit 4用のテストコード実装用APIとテストエンジンを提供

今回の環境

  • Java 11 (OpenJDK 11.0.2)
  • JUnit Platform 1.5.2
  • JUnit Jupiter 5.5.2
  • Gradle 6.0.1

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

ソースコード一覧

├── build.gradle
├── settings.gradle
└── src
    ├── main
    │   └── java
    │       └── myapp
    │           └── Calc.java
    └── test
        └── java
            └── myapp
                └── CalcTest.java

build.gradle

build.gradle
plugins {
  id 'java'
}

repositories {
  jcenter()
}

dependencies {
  // Junit Jupiter 5.5.2 を導入
  // 依存関係で以下等が導入される
  // junit-jupiter-api:5.5.2
  // junit-jupiter-engine:5.5.2
  // junit-jupiter-platform-engine:1.5.2
  testImplementation 'org.junit.jupiter:junit-jupiter:5.5.2'
}

test {
  // JUnit platform を使う設定
  useJUnitPlatform()

  testLogging {
    // テスト時の標準出力と標準エラー出力を表示する
    showStandardStreams true
    // イベントを出力する (TestLogEvent)
    events 'started', 'skipped', 'passed', 'failed'
    // 例外発生時の出力設定 (TestExceptionFormat)
    exceptionFormat 'full'
  }
}

参考:

settings.gradle

settings.gradle
rootProject.name = 'myapp'

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 の検証");
  }
}

参考:

テスト成功時の例

$ gradle test

> Task :test

myapp.CalcTest STANDARD_OUT
    CalcTest 開始

myapp.CalcTest > testMinus() STARTED

myapp.CalcTest > testMinus() STANDARD_OUT
    CalcTest のテストメソッドをひとつ開始
    testMinus を実行: 5 - 2 = 3
    CalcTest のテストメソッドをひとつ終了

myapp.CalcTest > testMinus() PASSED

myapp.CalcTest > testPlus() STARTED

myapp.CalcTest > testPlus() STANDARD_OUT
    CalcTest のテストメソッドをひとつ開始
    testPlus を実行: 2 + 3 = 5
    CalcTest のテストメソッドをひとつ終了

myapp.CalcTest > testPlus() PASSED

myapp.CalcTest STANDARD_OUT
    CalcTest 終了

BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 executed

テスト失敗時の例

$ gradle test

> Task :test FAILED

myapp.CalcTest STANDARD_OUT
    CalcTest 開始

myapp.CalcTest > testMinus() STARTED

myapp.CalcTest > testMinus() STANDARD_OUT
    CalcTest のテストメソッドをひとつ開始
    testMinus を実行: 5 - 2 = 3
    CalcTest のテストメソッドをひとつ終了

myapp.CalcTest > testMinus() FAILED
    org.opentest4j.AssertionFailedError: 5 - 2 = 3 の検証 ==> expected: <3> but was: <7>
        at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
        at org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
        at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
        at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:542)
        at myapp.CalcTest.testMinus(CalcTest.java:48)

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))
    );
  }
}

参考:

テスト失敗時の例

$ gradle test

> Task :test FAILED

myapp.CalcTest > testPlus() STARTED

myapp.CalcTest > testPlus() FAILED
    org.opentest4j.MultipleFailuresError: Multiple Failures (2 failures)
        org.opentest4j.AssertionFailedError: expected: <99> but was: <100>
        org.opentest4j.AssertionFailedError: expected: <11> but was: <60>
        at org.junit.jupiter.api.AssertAll.assertAll(AssertAll.java:80)
        at org.junit.jupiter.api.AssertAll.assertAll(AssertAll.java:44)
        at org.junit.jupiter.api.AssertAll.assertAll(AssertAll.java:38)
        at org.junit.jupiter.api.Assertions.assertAll(Assertions.java:2839)
        at myapp.CalcTest.testPlus(CalcTest.java:15)

1 test completed, 1 failed

FAILURE: Build failed with an exception.

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

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);
  }
}

参考資料

15
22
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
15
22