本文へスキップ
BecomeCoder

C#デザインパターンコース · 第2章 TDD ― テスト駆動開発 · レッスン16

TDD実践 ― 仕様変更に立ち向かう

ブラウザで完結

導入

TDDの真価は仕様変更のときに現れます。テストがあれば「変更で過去の機能を壊していないか」を一瞬で確認できます。割り勘計算を例に、仕様追加を安全に行いましょう。

図解

flowchart TB
    OLD["既存テスト(緑)"] --> CHG["仕様追加で実装を変更"]
    CHG --> CHK{"既存テストは緑のまま?"}
    CHK -->|はい| SAFE["過去の機能は無事 ✅"]
    CHK -->|いいえ| BUG["デグレを即検知 🛑"]
    style SAFE fill:#e8f5e9

サンプル

仕様が変わるのは実装ファイルだけ。テストファイルは基本的にそのまま残る——この非対称性がTDDの守りの強さです。

1. 実装(BillSplitter.cs)。仕様変更のときに手を入れるのはこちらです。

// 仕様: 割り勘。端数は切り上げ
public static class BillSplitter
{
    public static int Split(int total, int people)
    {
        if (people <= 0) throw new ArgumentException("人数は1以上");
        return (total + people - 1) / people;   // 切り上げ除算
    }
}

2. テスト(Program.cs)。過去の仕様を書き留めた資産です。実装を変えたら、ここが緑のままかを毎回確かめます。

Assert(BillSplitter.Split(3000, 3) == 1000, "3000/3=1000");
Assert(BillSplitter.Split(1000, 3) == 334,  "1000/3=334(切り上げ)");
Console.WriteLine("全テスト成功");

void Assert(bool c, string n) { if (!c) throw new Exception($"FAIL: {n}"); }
  • 仕様をテストとして書き出しておくと、実装変更のたびに全件を再確認できる
  • 既存テストが緑のまま=デグレ(過去機能の破壊)が起きていない証明
  • 「切り上げ除算」(a + b - 1) / bは実務頻出のテクニック
  • 変更するファイル(実装)と守るファイル(テスト)が分かれているので、差分レビューが読みやすい

演習

// 新仕様: 幹事は支払い免除(人数 - 1 で割る)
Assert(SplitExemptOrganizer(3000, 3) == 1500, "3000を幹事免除3人→1500");
Console.WriteLine("全テスト成功");

// TODO: 幹事を除いた (people - 1) 人で割り勘(切り上げ)する
//       SplitExemptOrganizer を実装してください
void Assert(bool c, string n) { if (!c) throw new Exception($"FAIL: {n}"); }
___
  • 期待される出力: 全テスト成功
ヒント1を見る

支払人数はpeople - 1。切り上げ除算を使います

ヒント2を見る

int SplitExemptOrganizer(int total, int people) { int payers = people - 1; return (total + payers - 1) / payers; }

まとめ

  • テストがあれば仕様変更後もデグレを即検知できる
  • 既存テストが緑=過去の機能を壊していない証明
  • テストは「実行できる仕様書」として資産になる

次回: 依存を偽物に差し替えるMoqです。

実際に動かしてみよう

このレッスンのサンプルは、実務と同じように役割ごとの .cs ファイルへ分けてあります。下のエディタは最初からその複数ファイルが入った状態で、上のタブでファイルを切り替えられます。そのまま「▶ 実行」を押せば全ファイルをまとめてコンパイルして動かせるので、クラスを足したりファイルをまたいで書き換えたりしながら進めましょう(演習は本文のコードをコピーして Program.cs のタブに貼り付ければ試せます)。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。

次のレッスンへ →