たなかのJava日記

どんなことをやったか(学んだか)、どこで詰まったか(わからなかったか)、どこで工夫したかの記録です。

Junitでテストケース実装、実装コードの修正を行う

 

//テストされるコード
package test;

/**
 * 足し算
 */
public class Calc {
    /**
     * 渡された2つの値で足し算を行う
     * @param a 一つ目の値
     * @param b 二つ目の値
     * @return 足し算の結果
     * @since 2022/11/12
     */
    public int add(int a, int b) {
        return a * b;
    }
}

//テストコード
package test;

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

class CalcTest {

    @Test
    void add() {
    }
}

テストの中身はまだ実装していませんがテストコード内で、[Ctrl]+[Shift]+[F10]を押して実行してみます。

このショートカットキーを使用した時は、テキストカーソル位置で実行の動作が変わるので注意です。
・テストメソッド内にカーソル有⇒そのテストメソッドのみ実行
・テストメソッド外&テストクラス内にカーソル有⇒テストクラスすべてのテストメソッド実行

ショートカットキーを使用しない場合
・テストクラス横の[すべて実行]ボタンを押すと、テストクラス内全てのテストメソッドを実行。
・テストメソッド横の[一つ実行](▶)ボタンを押すと、そのテストメソッドのみ実行できます。

とはいえ、現状はJunitのセットアップができて、テストメソッドに何も実装していない状態です。
なので、実行してもテストは成功します。
今回はテストメソッド(addメソッド)内に次の行を加えてテストを実装します。

■追加する行
assertEquals(4, new Calc().add(2,2), "2 + 2 = 4");

・構文
assertEquals(期待値, 実際の値[, テスト内容を表すメッセージ]);

//addメソッドに追加
package test;

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

class CalcTest {

    @Test
    void add() {
        assertEquals(4, new Calc().add(2,2), "2 + 2 = 4");
    }
}

★解説メモ
・assertEqualsはJunitが提供するアサーションメソッドと呼ばれるメソッド
・実行結果が期待した値になることを確認・検証するメソッド
アサーションメソッドは多数あるが、assertEqualsは最も基本的かつ重要
・ちなみにassertとは英語で「断言する」という意味で、
「このように動作すべきだ、そうでなければバグであると断言する」といった意味で使われる
・"実際の値"で評価された結果が"期待値"と等しい場合にはテストが成功
・等しくない場合は、AssertionFailedErrorというエラーが投げられる
・「テストの内容を表すメッセージ」は省略可だが、失敗したときに表示される
そのため、何をテストしているのか一目でわからないような場合は極力書くこと

■追加する行の実行結果について
実行結果ですが、テストが成功しています。
Calcクラスでは足し算を行うところで掛け算を行いましたが、成功してしまいました。
2*2と2+2は同じ4なのでバグを検出できなかったのです。
テストが成功する状態では何を直すべきかわからないし、
直したつもりででも直っているのか確認が取れません。
自動テストでは「前もってテストが失敗することを確認しておく」ことが重要です。

そこで「前もってテストが失敗することを確認しておく」ために、
次の一行を加えて再度実行してみます。

assertEquals(6, new Calc().add(2,4), "2 + 4 = 8");

//テストケースを追加
package test;

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

class CalcTest {

    @Test
    void add() {
        assertEquals(4, new Calc().add(2,2), "2 + 2 = 4");
        assertEquals(6, new Calc().add(2,4), "2 + 4 = 8");
    }
}


■テストケースを追加した実行結果
今度はテストが成功しました。
足し算の代わりに掛け算を行ってしまっている不具合を、検出できるテストが書けたことになります。
あとはCalcクラスに移動して実装を修正していきます。
テストクラスからCalcクラスに移動するときは、
[Ctrl]+[Shift]+[T]を使うと瞬時に移動できます。
[Ctrl]+[Shift]+[T]は実装コードとテストコードを相互にジャンプするショートカットキーです。
a * bをa + bに修正します。
[Ctrl]+[Shift]+[F10]で実行したいところですが、
このショートカットキーは、
"今開いているファイルのテストやmainメソッドの実行をする"
コマンドのため使えません。(やっても反応なし)
今、開いているのは修正したCalcクラスであり、テストクラスではないです。
また、Calcクラスにはmainもないので実行できないというわけです。
しかし、テストクラスに戻らなくても「最後に実行した設定で再実行」できるショートカットキーがあります。
それが[Shift]+[F10]です。
先ほどショートカットキーから[Ctrl]を無しにしたバージョンですね。
実行するとテストは成功し完了となります。

■テストクラス名について
多くの場合、"テストクラス"は"テスト対象のクラス"と対になるので、
「テスト対象クラス名 Test」という名前で作成します。

■テストメソッドについて
テストメソッドはいくつ実装しても良いのでテスト対象メソッド一つに対して複数実装してもOKです。
確認する項目が多い場合や、確認する内容・性質が異なる場合は積極的にテストメソッドを分けます。
テストメソッドを分けるメリットは、実装中やデバッグ中に「何が動作して何が動作していないのか」が分かりやすくなります。