15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

初めてのJUnit(基礎的な使い方)

Last updated at Posted at 2023-01-02

今までCOBOLが業務の主流でしたが、最近Javaも使うようになったので、ここらで一度Java単体テストの手法として、JUnitの初歩的な使用方法を学習しようと思います。

JUnitとは

JUnitについては、e-Wordsより以下のように記載されています。

JUnitとは、Java言語で開発されたプログラムの単体テスト(ユニットテスト)を行なうためのソフトウェア。また、そこで用いられるテストコードの記述体系を含むテストフレームワーク。
IT用語辞典 e-Wordsより

JUnitを使うことで、作成したJavaクラスやメソッドの単体テストコードが記載できるようになります。JUnitには、単体テストをするにあたって活用できるメソッドやアノテーションが提供されています。

この記事では、以下の環境で実施します。

環境 バージョン
端末 MacBook Air 2022 (M2)
OS macOS Ventura 13.0.1
Java JDK18
JUnit 5.6.0

テストクラス

基本的なテストクラスは、以下のとおりです。

public class BasicTest {
    
    public BasicTest() {
    }
    
    @BeforeAll
    public static void setUpClass() {
    }
    
    @AfterAll
    public static void tearDownClass() {
    }
    
    @BeforeEach
    public void setUp() {
    }
    
    @AfterEach
    public void tearDown() {
    }

    @Test
    @DisplayName("Comment")
    public void testSomeMethod() {
    }
    
}

それぞれのメソッド(アノテーション)には、役割があります。

アノテーション 解説
@BeforeAll テストクラスの最初に、必ず実行するセットアップメソッドです
@AfterAll テストクラスの最後に、必ず実行するティアダウンメソッドです
@BeforeEach 各テストメソッドの前に、必ず実行するセットアップメソッドです
@AfterEach 各テストメソッドの後に、必ず実行するティアダウンメソッドです
@Test 実際のテストロジックを書くメソッドです
@DisplayName JUnitテストクラス・メソッドの表示名です

@BeforeAllとコンストラクタの違い

コンストラクタは、インスタンス化時に一度だけ実行される初期化メソッドです。@BeforeAllと性質がよく似ているのですが、

  • @BeforeAllは全てのテストを実行する前に実行
  • コンストラクタは@BeforeEachの前に実行

されます。1

例えば、以下のようなテストコードを用意します。

public class BasicTest {
    
    public BasicTest() {
        System.out.println("Constructor");
    }
    
    @BeforeAll
    public static void setUpClass() {
        System.out.println("@BeforeAll");
    }
    
    @AfterAll
    public static void tearDownClass() {
        System.out.println("@AfterAll");
    }
    
    @BeforeEach
    public void setUp() {
        System.out.println("@BeforeEach");
    }
    
    @AfterEach
    public void tearDown() {
        System.out.println("@AfterEach");
    }

    @Test
    @DisplayName("テスト1")
    public void testSomeMethod1() {
        System.out.println("@Test(1)");
    }

    @Test
    @DisplayName("テスト2")
    public void testSomeMethod2() {
        System.out.println("@Test(2)");
    }
    
}

こちらを実行してみると

@BeforeAll
Constructor ←@BeforeEachの前に実行
@BeforeEach
@Test(1)
@AfterEach
Constructor ←@BeforeEachの前に実行
@BeforeEach
@Test(2)
@AfterEach
@AfterAll

となります。

もし、コンストラクタを最初の一度だけ動かすようにしたい場合は、

@TestInstance付加
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class BasicTest {
	...
}

とすれば、最初の一度だけ動くようになります。

アサーション

アサーションの意味については、e-Wordsにて、以下のように記載されています。

アサーションとは、表明、断言、主張などの意味を持つ英単語。プログラミングにおいて、あるコードが実行される時に満たされるべき条件を記述して実行時にチェックする仕組みをアサーションという。
IT用語辞典 e-Wordsより

JUnitでは、このチェックする仕組みが提供されており、Assertionsクラスのメソッドを用いて、値の検証を行います。

全ては書ききれませんので、上記サイトからいくつかピックアップしておきます。

assertEquals(A, B):AとBの同値判定

パラメータA、Bが同値であることを検証します。

assertEqueals(A, B)
@Test
@DisplayName("同値判定")
public void testSomeMethod1() {
    int varA = 1;
    int varB = 1;
    assertEquals(varA, varB);
}

例ではint型同士ですが、オーバーロードによって、様々な型やオブジェクトの比較が可能になっています。

assertTrue(A):Aがtrueであるか判定

パラメータAがtrueであることを検証します。大小比較用のアサートは提供されていないので、こちらを使用します。

assertTrue(A)
@Test
@DisplayName("コンディション判定")
public void testSomeMethod1() {
    int varA = 1;
    int varB = 2;
    assertTrue(varA < varB);
}

assertThrows(A, B):例外スロー判定

処理Bが例外Aを投げることを検証します。処理Bは、対象のメソッドを呼び出すか、ラムダ式でそのまま処理を記載します。

assertThrows(A, B)
@Test
@DisplayName("例外スロー判定")
public void testSomeMethod1() {
    assertThrows(Exception.class, () -> {
        throw new Exception("Exception is Throwed.");
    });
}

簡単な単体テストを実践してみる

ここで、簡単な単体テストを実施してみようと思います。

テストするコード

テストするコードは、パラメータの値に対して、Fizz/Buzz/FizzBuzzを返すメソッドです。

テストするコード
public class FizzBuzz {
    
    public String FizzBuzz (int number) {
        String str = "";
        if (number % 3 == 0) {
            str += "Fizz";
        }
        if (number % 5 == 0) {
            str += "Buzz";
        }
        return str;
    }
    
}

テストケース

今回は、以下のケースを検証します。

ケースNo. 実施条件(パラメータ) 想定結果(返却値)
ケース1 3で割り切れ、5で割り切れない値 Fizz
ケース2 3で割り切れず、5で割り切れる値 Buzz
ケース3 3でも5でも割り切れる値 FizzBuzz
ケース4 3でも5でも割り切れない値 (空文字)

テストコード

テストケースに基づいて作成したJUnitソースは以下のとおりです。

JUnitコード
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class FizzBuzzTest {
    
    private FizzBuzz fz;
    
    /**
     * FizzBuzzクラスはコンストラクタで一度だけインスタンス化
     * ※ @TestInstance(TestInstance.Lifecycle.PER_CLASS)のため、コンストラクタは一度しか実行しない
     */
    public FizzBuzzTest() {
        fz = new FizzBuzz();
    }

    /**
     * 実施条件:3で割り切れ、5で割り切れない値
     * 想定結果:Fizz
     */
    @Test
    @DisplayName("ケース1")
    public void testFizzBuzz1() {
        assertEquals("Fizz", fz.FizzBuzz(9));
    }
    
    /**
     * 実施条件:3で割り切れず、5で割り切れる値
     * 想定結果:Buzz
     */
    @Test
    @DisplayName("ケース2")
    public void testFizzBuzz2() {
        assertEquals("Buzz", fz.FizzBuzz(10));
    }
    
    /**
     * 実施条件:3でも5でも割り切れる値
     * 想定結果:FizzBuzz
     */
    @Test
    @DisplayName("ケース3")
    public void testFizzBuzz3() {
        assertEquals("FizzBuzz", fz.FizzBuzz(15));
    }
    
    /**
     * 実施条件:3でも5でも割り切れない値
     * 想定結果:(空文字)
     */
    @Test
    @DisplayName("ケース4")
    public void testFizzBuzz4() {
        assertEquals("", fz.FizzBuzz(8));
    }
    
}

検証結果

NetBeansなどのIDEでは、検証結果をグラフィカルに確認することができます。

Fig1.png

まとめ

初めてJUnitの基礎的な使い方を調べて、お気持ち程度の単体テストまで実施しました。調べていると、もっと色々な使い方がありましたので、もっと調べて活用できればと思います。

  1. 参考:https://b1san-blog.com/post/java/java-junit/#ライフサイクル

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?