04 テストの設計
03 章でテストの書き方を学びました。最後は「どんなテストを書くべきか」を自分で考える力を養います。テストは「書ける」だけでなく「何を試すべきかを洗い出せる」ことが本質です。
テスト対象の決め方
全部をテストしようとすると挫折します。優先順位をつけます。
- 最優先: ドメインロジック(純粋関数)
入力に対して出力が決まる関数(
toCartLine/sumSalesByTaxabilityなど)。速く・決定的にテストでき、バグが致命的になりやすい。 - 薄く: UI / DB / ルーティング 画面表示やDBアクセスは、ロジックを切り出した上で「繋ぎ込み」だけを軽く確認する。
- このハンズオンの事故も、原因は**ドメインロジックの判定(税率 vs 税区分)**にありました。だからそこを重点的にテストします。
ケースの洗い出し:3つの観点
あるロジックをテストするとき、最低この3種類を考えます。
| 観点 | 意味 | 例(消費税) |
|---|---|---|
| 正常系 | 想定どおりの入力 | 税率10%の課税商品 → 税込表示・課税売上 |
| 異常系 | 想定外・不正な入力 | 数量が負、価格が文字列、税区分が未知の値 |
| 境界値 | 条件の境目 | 税率 0%、価格 0円、数量 0、ちょうど割り切れる/割り切れない金額 |
02章のバグは、まさに**境界値「税率0%」**で表面化しました。境界値こそバグの巣です。
消費税題材での観点表
このシステムでテストすべきケースを、自分で表に起こしてみましょう。
税区分 × 税率の組み合わせ
| 税区分 | 税率 | 期待する表示 | 売上集計 |
|---|---|---|---|
| STANDARD(標準) | 10% | 税込 | 課税売上 |
| REDUCED(軽減) | 8% | 税込 | 課税売上 |
| STANDARD(標準) | 0% | 税込(課税のまま) | 課税売上 ← 本章の核 |
| EXEMPT(非課税) | ― | 非課税 | 非課税売上 |
「税率0%の課税商品」と「非課税商品」を区別できるかが、このシステムの一番のポイントです。
その他の観点
- 端数処理: 四捨五入か切り捨てか。
Math.floor/Math.roundで結果が変わる金額(例: 税抜 199円 × 8%)。 - 数量0 / 価格0: 合計が0になるケース。0円と「非課税」を混同していないか。
- 複数明細の合算: 課税と非課税が混ざった注文で、それぞれ正しく振り分けられるか。
- 集計: 課税売上・非課税売上への振り分け、課税売上割合(課税売上 ÷ 総売上)。
演習:穴埋めでケースを起こす
sections/04-test-design/01-design-cases に、未完成のテストファイルを用意します。観点表をもとに、自分でテストケースを書き足してください。
import { test } from 'node:test'import assert from 'node:assert/strict'import { toCartLine, sumSalesByTaxability } from '../src/domain/index.js'
// 例として1つだけ書いてありますtest('標準課税の商品は税率10%で税込表示になる', () => { const line = toCartLine({ name: 'ノートPC', price: 100000, tax_category: 'STANDARD', tax_rate: 0.1 }) assert.equal(line.label, '税込')})
// TODO: 税率0%の課税商品は「非課税」表示にならないことを確かめるテストを書く// TODO: 非課税商品は「非課税」表示になることを確かめるテストを書く// TODO: 課税と非課税が混ざった注文の集計を確かめるテストを書く// TODO: 端数(四捨五入/切り捨て)の境界を確かめるテストを書く書いたら node --test で実行し、ロジックの正しさ(あるいはバグ)を自分のテストで暴いてみましょう。
発展:割り算で税率を使う地雷
「税率0%」で壊れるパターンは、表示・集計だけではありません。税率を割り算の分母に使うコードは、0%で Infinity を生みます。
// 税額から、1%あたりの金額を逆算しようとすると…function pricePerTaxPercent(totalTax, taxRate) { return totalTax / taxRate // taxRate が 0 だと Infinity}「税率は必ず正の値」という前提が埋まっているコードは、こうした形でも潜んでいます。テスト設計では「この値が0/空/負だったら?」を常に問う癖をつけると、地雷を踏む前に見つけられます。
まとめ
- テストは「書ける」だけでなく「何を試すか洗い出せる」ことが本質
- 正常系・異常系・境界値の3観点で考える
- 消費税題材では「税率0%の課税商品 vs 非課税商品」が最重要の境界
- 「この値が0/負/空だったら?」と問い続けると、バグの巣を先回りできる
00 はじめに に戻って、全体の流れを振り返ってみましょう。