Javaの単体テストはどこまで書く?テストケースの考え方とカバレッジの目安

最終更新日

Schoo Java入門 中級 第3回 単体テストによるビジネスロジック検証

本記事は、Schooの「Java入門 中級【2026年版】」第3回「単体テストによるビジネスロジック検証」を学ぶ前後に、単体テストでどこまでテストケースを考えればよいかを整理したい方向けの記事です。

単体テストを学び始めると、「入力できる値を全部試す必要があるのか」「どの値を選べば十分なのか」で迷いやすくなります。結論から言うと、すべての値を試す必要はありません。ただし、仕様の分岐、境界値、異常値、重要な業務ルールは意識して選ぶ必要があります。

Schoo コースページ:Java入門 中級【2026年版】

テストケースは仕様文から作る

テストケースは、思いつきで値を並べるものではありません。まず仕様文を読み、条件と期待する結果を分けます。そのうえで、各条件を確認できる入力値を選びます。

たとえば、次の仕様からテストケースを作るとします。

購入金額が5000円以上なら送料は0円。5000円未満なら送料は500円。購入金額が0円未満の場合は例外とする。

手順1:仕様文を条件と期待結果に分ける

最初に見るのは、仕様文の中にある「なら」「場合」「以上」「未満」のような言葉です。これらは、プログラムの条件分岐やテストケースの候補になりやすい表現です。

図解:仕様文を条件ごとに分解する
仕様文
購入金額が5000円以上なら送料は0円。
5000円未満なら送料は500円。
0円未満の場合は例外。
条件
意味
期待結果
amount < 0
0円未満は不正な入力
例外
amount >= 5000
送料無料になる条件
0
amount < 5000
送料がかかる条件
500
最初にやることは、JUnitを書くことではなく、仕様文を条件と期待結果に分けることです。

ここで大事なのは、先にJUnitコードを書かないことです。まず「この条件なら、この結果になる」という対応を表にします。

図解:条件分岐ごとにテストケースを置く
if (amount < 0) {
  throw …
} else if (amount >= 5000) {
  return 0;
} else {
  return 500;
}
異常系
-1
例外になる
境界値
4999 / 5000
条件の分かれ目
代表値
3000 / 10000
普通の入力
条件分岐がある場合は、それぞれのルートを通る値を少なくとも1つずつ考えます。

手順2:テストケース仕様書の列を決める

実務でテストケースを整理する場合は、表にして残すことがあります。最初は難しい書式にする必要はありません。少なくとも、確認観点、前提・条件、入力値、期待結果、確認方法が分かれば、あとからJUnitコードに変換しやすくなります。

図解:テストケース仕様書の列はこの順番で考える
確認観点
何を確かめるか
前提・条件
どの分岐か
入力値
何を渡すか
期待結果
何になるべきか
確認方法
assertEquals / assertThrows
テストケース仕様書は、JUnitコードを書く前に「確認したいこと」を言葉で固定するために使います。

確認観点には、「5000円未満の送料」「5000円ちょうどの境界」「0円未満の入力」のように、何を確かめたいのかを書きます。入力値だけを書くと、なぜその値を選んだのかが分からなくなりやすいためです。

手順3:各条件から入力値を選ぶ

条件を分けたら、入力値を選びます。このとき、代表値、境界値、異常値に分けると、何を選べばよいかが具体的になります。

  • 代表値:その条件に普通に入る値
  • 境界値:条件が切り替わる直前、ちょうど、直後の値
  • 異常値:仕様上、受け付けない値

送料計算なら、300010000 は代表値、49995000 は境界値、-1 は異常値として考えられます。

図解:条件から入力値を選んでテストケースにする
種類
仕様から見た条件
選ぶ入力値
期待結果
JUnit
代表値
5000円未満
3000
500
assertEquals
境界値
5000円の直前
4999
500
assertEquals
境界値
5000円ちょうど
5000
0
assertEquals
代表値
5000円以上
10000
0
assertEquals
異常値
0円未満
-1
例外
assertThrows
テストケース表は、条件、入力値、期待結果、JUnitの確認方法を1行ずつ対応させて作ります。

手順4:テストケース仕様書に記入する

入力値を選んだら、テストケース仕様書として1行ずつ整理します。ここでは「なぜその値を確認するのか」が分かるように、確認観点と前提・条件も書きます。

記入例:テストケース仕様書として整理する
No.
確認観点
前提・条件
入力値
期待結果
JUnitでの確認
TC-001
5000円未満の送料
通常の購入金額
3000
500
assertEquals(500, calculateFee(3000))
TC-002
5000円直前の境界
送料無料にならない最大値
4999
500
assertEquals(500, calculateFee(4999))
TC-003
5000円ちょうどの境界
送料無料になる最小値
5000
0
assertEquals(0, calculateFee(5000))
TC-004
5000円以上の送料
通常の購入金額
10000
0
assertEquals(0, calculateFee(10000))
TC-005
0円未満の入力
不正な購入金額
-1
例外
assertThrows(...)
テストケース仕様書では、値だけでなく「なぜその値を選んだのか」が分かるように確認観点を書きます。

この表があると、レビューするときにも「5000円ちょうどの確認が抜けていないか」「異常値の確認があるか」を見つけやすくなります。

手順5:まず最低限のテストケースをそろえる

最初から完璧なテストケースを作ろうとすると迷います。まずは、次の3つがそろっているかを確認します。

  • 正常に処理される代表値
  • 条件が切り替わる境界値
  • 仕様上受け付けない異常値
図解:テストケースは優先順位をつけて考える
優先度
確認すること
選ぶ値の例
目的
まず必須
仕様に書かれた各分岐を通る値
-1, 3000, 10000
大きな動きの確認漏れを防ぐ
次に重要
条件が切り替わる境界値
4999, 5000, 5001
>>= のミスを見つける
必要なら追加
実務上よく使う値や不具合が怖い値
0, 1, 上限値など
仕様だけでは見えにくいリスクを見る
増やしすぎ注意
同じ意味の値を何個も並べる
3001, 3002, 3003
テストが多いだけで発見力が上がりにくい
テストケースは数を増やせばよいのではなく、失敗したときに意味のある値を優先して選びます。

たとえば 300030013002 は、送料計算では同じ「5000円未満」のルートを通ります。もちろんまったく無意味ではありませんが、最初に増やすべき値ではありません。

それよりも、49995000 のように結果が切り替わる値を確認したほうが、条件式のミスを見つけやすくなります。

手順6:テストケース仕様書をJUnitコードにする

テストケース仕様書ができたら、表の1行をJUnitコードへ変換します。戻り値を確認する行は assertEquals、例外を確認する行は assertThrows にします。

assertEquals(500, calculator.calculateFee(4999));
assertEquals(0, calculator.calculateFee(5000));
assertEquals(0, calculator.calculateFee(5001));

このように境界の前後を確認すると、条件式を >= ではなく > と書いてしまった場合にも気づきやすくなります。

図解:テストケース表をJUnitコードに変換する
表の1行
入力値:4999
期待結果:500
確認方法:assertEquals
JUnitコード
assertEquals(500, calculator.calculateFee(4999));
表の「期待結果」を第1引数、「実際にメソッドを呼び出した結果」を第2引数にすると、JUnitコードへ変換できます。

異常値の行は、戻り値を比べるのではなく、例外が通知されることを確認します。

assertThrows(
    IllegalArgumentException.class,
    () -> calculator.calculateFee(-1)
);

テストケース仕様書をもとにすると、テストコード全体は次のようになります。

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;

class ShippingFeeCalculatorTest {

    @Test
    void testCalculateFee() {
        ShippingFeeCalculator calculator = new ShippingFeeCalculator();

        assertEquals(500, calculator.calculateFee(3000));  // TC-001
        assertEquals(500, calculator.calculateFee(4999));  // TC-002
        assertEquals(0, calculator.calculateFee(5000));    // TC-003
        assertEquals(0, calculator.calculateFee(10000));   // TC-004
    }

    @Test
    void testCalculateFeeThrowsExceptionWhenAmountIsNegative() {
        ShippingFeeCalculator calculator = new ShippingFeeCalculator();

        assertThrows(
            IllegalArgumentException.class,
            () -> calculator.calculateFee(-1)              // TC-005
        );
    }
}

コメントの TC-001 から TC-005 は、テストケース仕様書の番号と対応しています。仕様書とテストコードを対応させると、どのテストケースがどのコードで確認されているかを追いやすくなります。

手順7:足りないテストと増やしすぎたテストを見分ける

テストケースが足りない状態とは、仕様の分岐や境界が確認できていない状態です。一方で、増やしすぎた状態とは、同じ意味の値ばかりを増やしている状態です。

図解:足りないテストと増やしすぎたテスト
足りない
3000, 10000
代表値だけで、境界や異常値がない
ちょうどよい
-1, 3000, 4999, 5000, 5001, 10000
代表値、境界値、異常値がそろっている
増やしすぎ
3000, 3001, 3002, 3003, 3004…
同じ分岐を似た値で何度も確認している
初学者が迷ったときは、「足りない」よりも「ちょうどよい」に近づけることを目標にします。

まずは「各分岐を通る値があるか」「境界値を見ているか」「異常値を見ているか」を確認します。そのうえで、業務上ミスが大きな問題になる値があれば追加します。

カバレッジは目安であってゴールではない

カバレッジは、テストを実行したときに、プログラムのどの行や分岐が通ったかを示す目安です。カバレッジが高いことは大切ですが、それだけで十分とは限りません。

図解:カバレッジは通った場所の目安
if (amount >= 5000) {
  return 0;
} else {
  return 500;
}
安心とは限らない
行が通っていても、5000 ちょうどを試していなければ、>>= の間違いを見逃すことがあります。
カバレッジは確認した範囲を知るための目安であり、テストケースの選び方そのものを保証するものではありません。

たとえば、5000円以上のルートと5000円未満のルートがどちらも通っていても、5000 ちょうどを試していなければ、境界の確認としては弱くなります。

カバレッジを見るときは、「行が通ったか」だけでなく、「その行をどの値で通したか」もセットで考えます。テストケース表に入力値と期待値を書いておくと、カバレッジの数字だけでは見えない確認漏れに気づきやすくなります。

どこまで書くかの目安

初学者のうちは、次の観点でテストケースを考えると、どこまで書くべきか判断しやすくなります。

図解:どこまでテストするかの目安
分岐
各ルートを1回以上通る値を選ぶ
境界
条件が切り替わる直前・ちょうど・直後を見る
異常
受け付けない値を渡したときの動きを見る
重要度
業務上の影響が大きい条件を優先する
初学者のうちは、この4つを確認できているかを目安にすると、テストケースを考えやすくなります。

すべての組み合わせを最初から試そうとする必要はありません。まずは、条件分岐、境界値、異常系、重要な業務ルールを押さえることを目標にします。

反対に、画面表示の文言、ログの細かい出力、あとから簡単に目視できるだけの処理などは、単体テストで細かく確認しすぎると、修正のたびにテストが壊れやすくなることがあります。単体テストでは、計算、判定、変換、例外など、プログラムの判断が入る部分を優先します。

つまり、テストケースの数ではなく、仕様上の大事な判断を確認できているかで考えることが大切です。

確認問題

次の仕様について、テストケース仕様書を作り、その内容をJUnitコードにしてみてください。

点数が80点以上ならA、60点以上80点未満ならB、60点未満ならC。点数が0未満または100を超える場合は例外とする。

確認観点、前提・条件、入力値、期待結果、確認方法を表に整理してから、JUnitコードに変換してみましょう。

演習後の確認:こちらのページを使って、自分で考えた内容を見直せます。

まとめ

  • テストケースは、仕様文を条件と期待結果に分けて作る
  • テストケース仕様書には、確認観点、前提・条件、入力値、期待結果、確認方法を書く
  • 代表値、境界値、異常値を選ぶと、確認すべき値を決めやすい
  • テストケース仕様書の1行を、assertEqualsassertThrows に変換する
  • カバレッジは通った場所の目安であり、十分さそのものではない

関連する記事

シェアする