JUnitの基本①　基礎知識～簡単なテストメソッドの作成

## はじめに
本記事では、JUnitの基礎知識から簡単なテストメソッドの作成まで説明していきます。

## 対象者
- Javaの基礎知識を持っている方
- JUnitに初めて触れる方、もしくは少し触れたことのある方

## 動作環境
- Eclipse 2022（Pleiades All in One）

## 事前準備
Eclipse（Pleiades All in One）のインストールについては以下の記事で紹介していますので、ご参考ください。
[Spring Bootを使ったREST APIの基本構築から動作確認まで①-Pleiades All in One](https://qiita.com/pomecode/items/dcd2353d1f3b49dc23ff#pleiades-all-in-one)

## ユニットテストとは
JUnitの話に入る前に、まずユニットテストについて簡単に説明します。
ユニットテストとは、ソフトウェアテストにおける最小単位のテストであり、主に個々のクラスやメソッドを対象として正しく動作するか検証するために行います。
通常、ソフトウェア開発工程の初期段階で実施されます。

また、ユニットテストはプログラムに修正が加えられるたびに繰り返し実行する必要がありますが、手動で行うと手間がかかり非効率です。JUnitはこのテストを自動化するためのツールであり、効率的で繰り返し可能なユニットテストの実施を支援してくれます。

## JUnitとは
JUnitは、Javaでユニットテストを実施するためのテスティングフレームワークです。
テストコードを記述することで、テストを自動で実行したり、テスト結果の判定や集計を自動で行ったりするなど、様々な機能を提供しています。これにより、ユニットテストを効率的かつ効果的に実施することが可能となります。

さらに、JUnitは多くのIDE（統合開発環境）でサポートされており、Eclipseなどでは標準で組み込まれています。そのため、適切なimport文を記述するだけで、JUnitの機能をすぐに利用することができます。

### テストクラスとテストメソッド
JUnitではテスト対象クラスに対して、同プロジェクト内にテストクラス用のソースフォルダ、同階層のパッケージ、テストクラスを作成します。
テストクラスの名前は、テスト対象クラスのクラス名の後に大文字から始まる"Test"とつけることが多いです。

**例）**
```
src
  ∟junit.demoパッケージ
    ∟User.java        ・・・テスト対象クラス
test                  ・・・テストクラス用のソースフォルダ
  ∟junit.demoパッケージ
    ∟UserTest.java    ・・・テストクラス
```

### テストメソッドの記法
テストメソッドは、JUnitによるユニットテストの基本単位であり、テストクラスの中に記述します。
記述ルールとしては、@&#xFFF0;Testアノテーションを付けることと、戻り値型をvoidにすることです。
@&#xFFF0;Testアノテーションを付けることで、JUnitがテストメソッドと判断して、JUnitテストを実行してくれます。

```java
@Test
void テストメソッド名() {
    // テストコード（テスト対象となるクラスやメソッドの振る舞いの検証）
}
```

### アサーションとは
テストケースの作成に入る前に、アサーションについて触れておきます。
アサーションとは、値の比較検証を行うことです。
org.junit.jupiter.api.Assertionsクラスを使用しますが、こちらはアサーションを行うための基本クラスでアサーションメソッドが多く定義されています。

基本的なアサーションメソッドは以下になります。

|メソッド名|利用例|説明|
|--|--|--|
|assertEquals|assertEquals(期待値, 実測値)|期待値と実測値が等しい場合にテスト成功|
|assertNotEquals|assertNotEquals(期待値, 実測値)|期待値と実測値が等しくない場合にテスト成功|
|assertTrue|assertTrue(実測値)|実測値がTrueの場合にテスト成功|
|assertFalse|assertFalse(実測値)|実測値がFalseの場合にテスト成功|
|assertNull|assertNull(実測値)|実測値がNullの場合にテスト成功|
|assertNotNull|assertNotNull(実測値)|実測値がNullではない場合にテスト成功|
|assertThrows|assertThrows(発生するであろう例外のクラス名, テスト対象の処理実行)|テスト対象の処理を実行した際、指定した例外が発生したらテスト成功|
|fail|fail("失敗時のメッセージ"※任意)|テストを失敗させるアサーションメソッド|
|assertArrayEquals|assertArrayEquals(期待値, 実測値)|配列同士の期待値と実測値が等しい場合にテスト成功|
|assertAll|assertAll("エラー時に出力されるメッセージ", () -> アサーション, () -> アサーション, ...)|複数のテストを実行でき、1つのテストに失敗しても残りのテストを全て実行|

### 実装
それではテスト対象となるクラス、およびJUnitを用いたテストクラスを作成していきましょう。

#### テスト対象クラスの作成
まずは、Eclipseで新規Javaプロジェクトを作成し、プロジェクト名は"JUnitDemo"とします。
srcの下に"junit.demo"パッケージを作成し、その下に"User"クラスを作成してください。
テスト対象クラスであるUser.javaの中身は以下とします。

```java:User.java
package junit.demo;

public class User {
	private String name;
	private int age;

	public User(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public boolean isAdult() {
		return age >= 18; // 成人かどうかを判定
	}
}
```

#### テストクラスの作成
前述の通り、JUnitではテスト対象クラスに対して、同プロジェクト内にテストクラス用のソースフォルダ、同階層のパッケージ、テストクラスを作成します。
プロジェクト"JUnitDemo"を選択して右クリックし、新規フォルダーの作成から"test"フォルダを作成してください。
作成した"test"フォルダはビルド・パスに追加されていないため、"test"フォルダを右クリックし、[ビルド・パス]-[ソース・フォルダーとして使用]を押下して、ビルド・パスに追加します。

次に、"test"フォルダの配下に"junit.demo"パッケージを作成し、テスト対象クラスとパッケージの階層を揃えます。

続いて、テストクラスの作成です。
新規で1から作成しても良いですが、Eclipseのテンプレート機能を使用することも可能です。
User.javaを開き、Ctrl＋9を押下することでテストクラスを作成できます。
デフォルトではスーパークラスの欄に入力がありますが、今回は不要なので削除してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050193/59a9a046-f8a7-4b82-9de2-0416900390a3.png)

次画面で作成するテストメソッドを選択しますが、今回はインスタンス生成時に値が正しくセットされているかと、成人かどうかの判定ロジックが正しく動作しているかを確認したいため、コンストラクタとisAdultメソッドにチェックを入れて完了を押下してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050193/5f71f9ca-01d8-4952-ac92-02e1f6fa6c45.png)

作成されたテストクラスはデフォルトでfailメソッドが定義されています。
試しにJUnitを実行してみましょう。
クラス名：UserTestを選択し、右クリックで[実行]-[JUnitテスト]を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050193/bab35260-18ec-490f-99e2-f32a82589065.png)

failメソッドが定義されているため、以下のように2件実行され、2件とも失敗していることが分かります。
※メソッドを選択してJUnitテストを実行すると、選択したメソッドに対してのみテストが実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050193/0f18e766-5fe8-40db-b9d7-e5d6b0b3dfce.png)

#### テストメソッドの作成
今回はユーザーの生成と成人かどうかの判定ロジックに対してテストを行うため、テストメソッドは以下のように記述しています。
※ユーザー生成のテストメソッドは初期化の確認のため、メソッド名を"testUserInitialization"としています。

```java:
package junit.demo;

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

import org.junit.jupiter.api.Test;

class UserTest {

	// 正常なユーザーの生成をテスト
	@Test
	void testUserInitialization() {
		User user = new User("Alice", 25);
		
		assertEquals("Alice", user.getName()); // Nameの検証
		assertEquals(25, user.getAge()); // Ageの検証
	}

	// 成人かどうかの判定ロジックをテスト
	@Test
	void testIsAdult() {
		User adultUser = new User("Bob", 18);
		User minorUser = new User("Carol", 17);
		
		assertTrue(adultUser.isAdult()); // 成人と判定されるべきなのでTrue
		assertFalse(minorUser.isAdult()); // 成人と判定されるべきではないのでFalse
	}

}
```

testUserInitializationメソッドではassertEqualsを使用して、作成したユーザーの名前が"Alice"、年齢が25と一致しているかどうかを検証しています。
testIsAdultメソッドではassertTrueとassertFalseを使用して、18歳のユーザーが成人と判定されていることと、17歳のユーザーが成人と判定されていないことを検証しています。

また、2点補足と注意点です。
- JUnit4ではアクセス修飾子：publicが必要だが、JUnit5ではアクセス修飾子なしでも問題なし
※今回はJUnit5のため、アクセス修飾子を付けていません
- importするアサーションのクラスはAssertionsクラス

#### テストクラスの実行
テストメソッドの準備ができたら、JUnitテストを実行してみましょう。
実行すると、2件とも正常終了していることが確認できます。
※緑のチェックが表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050193/e73d76fc-937f-4f9e-a0c7-4e97e61aca7f.png)

## おわりに
今回はJUnitに関する基礎知識と簡単なテストメソッドの作成について説明してきました。
次回の記事では、実際の開発で役立つ基本機能についてもう少し掘り下げて説明していますので、良ければそちらもご覧ください。
[JUnitの基本②　基本機能の活用](https://qiita.com/pomecode/private/f3ce7b190a0a7112b33c)