コンテンツにスキップ

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 はじめに に戻って、全体の流れを振り返ってみましょう。