CSのTips一覧

テストの期待値は、実装を写す前に仕様の具体例から決める

入力と期待する振る舞いを先に具体化し、実際の結果と比べる。内部の関数名や呼び出し回数を固定するのは、それ自体が守りたい条件のときに絞る。

用語

アサーション
実際の結果が期待する条件を満たすかを確認し、違えばテストを失敗させる仕組み。
振る舞い
入力に対する出力・エラー・状態変化など、利用する側から確認できる動作。
リファクタリング
外から見える振る舞いを保ちながら、内部の構造を変えること。

図と例

仕様の境目の具体例を、実装から独立した期待値にする

仕様:小計3,000円以上は送料無料 → 例:2,999円・3,000円・3,001円 → 期待送料:500円・0円・0円 → 実際の結果をアサーションで比較

仮定の例:送料は小計3,000円以上なら0円、それ未満は500円。2,999→500、3,000→0、3,001→0を確認する。内部の判定を関数へ分けても、この期待値は変わらない。実装が誤って「3,000円より大きい」としていれば、3,000円のケースが検出する。

実際のサービス・製品では

  • Google Testing Blog

    公開APIの振る舞いを検証することで、内部の実装変更に強いテストにする考え方を説明している。実装詳細の検証が必要な場合も区別している。

    資料を読む
  • pytest

    parametrizeで入力と期待結果の組を複数定義し、同じテストを各ケースで実行できる。

    資料を読む

解説

最初の単体テストやバグ修正の回帰テストに使う。仕様が曖昧なら、期待値をコードから推測する前に具体例で確認する。外部への副作用を差し替えても、戻り値・エラー・必要な状態変化を確認する。

実装と同じ計算式をテスト側にも書くと、式の間違いまで複製して緑になることがある。まず仕様から入力と期待値を具体的に決め、アサーションで照合する。たとえば「小計が3,000円以上なら送料無料」なら2,999円・3,000円・3,001円を用意し、送料をそれぞれ決める。振る舞いが同じリファクタリングでは、主要な期待値を変えずに確かめられるテストが役立つ。実装詳細の検証も、重複送信の防止など必要な契約なら有効だが、単に今のコードを固定するためには増やさない。網羅率が高くても期待値の正しさまでは保証しない。

トレードオフ

公開された操作の結果を確認する
得るもの:内部を整理しても主要な期待値を保ちやすい
払うもの:内部の不要な処理や性能劣化は別の確認が必要な場合がある
必要な依存先への呼び出しも確認する
得るもの:二重送信など、呼び出し自体の契約を守れる
払うもの:契約でない内部の順序や回数まで固定すると変更に弱くなる

さらに学ぶ

チェック

「小計3,000円以上で送料無料」を実装した。境目の誤りを最も直接見つける期待値は?

  1. 内部の補助関数が今と同じ名前で呼ばれる
  2. 小計3,000円の送料が0円になる
  3. テストも実装と同じ比較式で送料を計算する
解答と解説

小計3,000円の送料が0円になる

3,000円ちょうどの期待値は、以上とより大きいの取り違えを検出する。補助関数の名前は送料の仕様を確認しない。同じ比較式を複製すると、同じ境界の誤りをテストにも持ち込むことがある。