今回やること
年齢から登録可否を判定する関数を題材に、同値分割と境界値分析でケースを選び、Node.jsの標準テスト機能で実行します。
進め方は次のとおりです。
- 仕様を文章で決める
- 入力を同じ結果になるグループへ分ける
- 結果が切り替わる境界を見つける
- 境界の直前・一致・直後を表にする
- テストを実行して期待結果と比べる

境界値テストとは
境界値テストは、結果が切り替わる値の近くを重点的に確認する方法です。
「18歳以上なら登録できる」という条件では、17歳と18歳の間で結果が変わります。20歳だけで確認すると、age > 18という間違いを見逃します。17、18、19を試せば、少ないケースで発見できます。
仕様を決める
今回は次の仕様を使います。
- 入力は年齢を表す整数
- 入力できる範囲は1〜20
- 1〜17歳は登録できない
- 18〜20歳は登録できる
- 範囲外や整数でない値はエラー
年齢の最小刻みは1です。境界の直前と直後は1小さい値、1大きい値です。入力範囲や刻みが不明なら、テストを書く前に確認します。
同値分割と境界値分析の違い
同値分割は、同じ結果になると考えられる入力をグループに分ける方法です。
今回の入力は4つの同値クラスに分けられます。
| 同値クラス | 入力 | 期待結果 |
|---|---|---|
| 下限より小さい | 0以下 | エラー |
| 登録不可 | 1〜17 | false |
| 登録可能 | 18〜20 | true |
| 上限より大きい | 21以上 | エラー |
各グループから代表値を選びます。境界値分析は、グループの境目を詳しく確認する方法です。
- 同値分割:入力全体を広く見る
- 境界値分析:結果が変わる端を詳しく見る
直前・一致・直後を表にする
今回の境界は、下限1、登録開始18、上限20の3つです。
| 境界 | 直前 | 一致 | 直後 |
|---|---|---|---|
| 下限1 | 0 → エラー | 1 → false | 2 → false |
| 登録開始18 | 17 → false | 18 → true | 19 → true |
| 上限20 | 19 → true | 20 → true | 21 → エラー |
19は2つの境界で候補になりますが、同じ期待結果なので1回で十分です。
三点法は、整数で最小刻みが1と決まっている今回の仕様で使えます。小数を許す場合は、先に0.1や0.01などの最小刻みを決めます。
Node.jsでテストを実行する
作業用フォルダに registration.test.mjs を作り、次のコードを保存してください。
import assert from "node:assert/strict";
import test from "node:test";
function canRegister(age) {
if (!Number.isInteger(age)) {
throw new TypeError("age must be an integer");
}
if (age < 1 || age > 20) {
throw new RangeError("age must be between 1 and 20");
}
return age >= 18;
}
test("入力範囲の下限を確認する", () => {
assert.throws(() => canRegister(0), RangeError);
assert.equal(canRegister(1), false);
assert.equal(canRegister(2), false);
});
test("登録開始の境界を確認する", () => {
assert.equal(canRegister(17), false);
assert.equal(canRegister(18), true);
assert.equal(canRegister(19), true);
});
test("入力範囲の上限を確認する", () => {
assert.equal(canRegister(20), true);
assert.throws(() => canRegister(21), RangeError);
});
test("整数ではない入力を拒否する", () => {
assert.throws(() => canRegister(18.5), TypeError);
});
ターミナルでファイルを保存したフォルダへ移動し、実行します。
node --test registration.test.mjs
成功を確認する
成功すると、結果に次の数が表示されます。
# pass 4
# fail 0
表示の細部は環境で異なります。4件成功、失敗0件なら完了です。age >= 18を一時的にage > 18へ変えると18歳のテストが失敗します。確認後は>=へ戻します。
境界値テストを作る5手順
- 型・範囲・刻みを書く:整数か小数か、最小値と最大値はいくつかを確認します。
- 同値クラスに分ける:同じ結果になる正常入力と範囲外入力を整理します。
- 境界を見つける:「以上」「未満」などの条件と入力範囲の端に注目します。
- 三点を選ぶ:直前・一致・直後の期待結果を書き、重複値はまとめます。
- 仕様と比べる:失敗したら、実装とテストのどちらが仕様と違うか確認します。
よくあるつまずき
- 代表値だけを試す:20歳だけでなく、登録開始の17・18・19も試します。
- 「以上」を取り違える:「18歳以上」は18を含むため
age >= 18です。 - 切り替え条件だけを見る:入力範囲の下限1と上限20も境界です。
- 実装から期待値を作る:同じ間違いを写さず、仕様と表から決めます。
練習
次の仕様で、同値クラスと境界値を考えてください。
- 参加人数は1〜30の整数
- 1〜9人は通常料金
- 10〜30人は団体料金
- 範囲外や整数でない値はエラー
- 同値クラスを4つ書く
- 下限1、団体料金開始10、上限30の直前・一致・直後を書く
node:testで確認するなら、どの値をテストするか書く
解答・確認基準
同値クラスは、0以下、1〜9、10〜30、31以上です。
境界値は次のようになります。
- 下限:0はエラー、1と2は通常料金
- 団体料金開始:9は通常料金、10と11は団体料金
- 上限:29と30は団体料金、31はエラー
0と31は範囲外、1と30は許可範囲の端、9と10は料金が切り替わる両側です。2、11、29は境界を越えた側でも同じ結果が続くことを確認します。非整数の10.5も追加します。
まとめ
- 同値分割は、同じ結果になる入力をグループに分ける
- 境界値分析は、結果が切り替わる端を詳しく確認する
- 整数刻み1なら、境界の直前・一致・直後を選べる
- 切り替え条件だけでなく、入力範囲の上下限も確認する
- 期待結果は実装ではなく仕様から作る
次のステップ
次は、テストを先に書いてから実装するTDD入門へ進みましょう。