今まで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.Lifecycle.PER_CLASS)
public class BasicTest {
...
}
とすれば、最初の一度だけ動くようになります。
アサーション
アサーションの意味については、e-Wordsにて、以下のように記載されています。
アサーションとは、表明、断言、主張などの意味を持つ英単語。プログラミングにおいて、あるコードが実行される時に満たされるべき条件を記述して実行時にチェックする仕組みをアサーションという。
IT用語辞典 e-Wordsより
JUnitでは、このチェックする仕組みが提供されており、Assertionsクラスのメソッドを用いて、値の検証を行います。
全ては書ききれませんので、上記サイトからいくつかピックアップしておきます。
assertEquals(A, B)
:AとBの同値判定
パラメータA、Bが同値であることを検証します。
@Test
@DisplayName("同値判定")
public void testSomeMethod1() {
int varA = 1;
int varB = 1;
assertEquals(varA, varB);
}
例ではint型同士ですが、オーバーロードによって、様々な型やオブジェクトの比較が可能になっています。
assertTrue(A)
:Aがtrueであるか判定
パラメータAがtrueであることを検証します。大小比較用のアサートは提供されていないので、こちらを使用します。
@Test
@DisplayName("コンディション判定")
public void testSomeMethod1() {
int varA = 1;
int varB = 2;
assertTrue(varA < varB);
}
assertThrows(A, B)
:例外スロー判定
処理Bが例外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ソースは以下のとおりです。
@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では、検証結果をグラフィカルに確認することができます。
まとめ
初めてJUnitの基礎的な使い方を調べて、お気持ち程度の単体テストまで実施しました。調べていると、もっと色々な使い方がありましたので、もっと調べて活用できればと思います。