SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

C#で始めるテスト駆動開発入門

TDDで仕様変更とデバッグをする方法

C#で始めるテスト駆動開発入門(4)

  • X ポスト
  • このエントリーをはてなブックマークに追加

サンプルコード

 TDDではおなじみのFizzBuzzです。FizzBuzz問題をご存知ない方は、Wikipediaの記事などを参照してください。バグを埋め込むために、わざとswitch文を使った変な実装にしてあります。

FizzBuzzのテストコード
using NUnit.Framework;
using CsTdd04.FizzBuzz;

namespace CsTdd04.FizzBuzzTest {
  [TestFixture]
  public class FizzBuzzerTest {
    [TestCase(1, "1")]
    [TestCase(3, "Fizz")]
    [TestCase(5, "Buzz")]
    [TestCase(6, "Fizz")]
    [TestCase(9, "Fizz")]
    [TestCase(10, "Buzz")]
    [TestCase(12, "Buzz")]
    [TestCase(15, "FizzBuzz")]
    public void SayTest(int n, string expected) {
      Assert.That((new FizzBuzzer()).Say(n), Is.EqualTo(expected));
    }
  }
}
FizzBuzzの製品コード
namespace CsTdd04.FizzBuzz {
  public class FizzBuzzer {
    public string Say(int n) {
      switch (n) {
        case 3:
        case 6:
        case 9:
          return "Fizz";
        case 5:
        case 10:
        case 12:
          return "Buzz";
        case 15:
          return "FizzBuzz";
        default:
          return n.ToString();
      }
    }
  }
}

仕様追加

ある日の朝

エライ人「あ、b君、b君! 昨日の仕様だけどね」
b君「なんでしょう?」
エライ人「言い忘れたけど。あれって、1から始まるんだよね…」
b君「そうです」
エライ人「じゃ、当然だけどゼロのときは例外にしてね」
b君「はぁ」(そんな呼び出しするわけないじゃん…)

 引数がゼロの時(ニュアンスを汲み取ると負の時もでしょう)、文字列を返さずに例外を投げて欲しいという仕様追加です。

 作業に取り掛かる前に、オールGREENを確認します。そうしたら、追加された仕様を表現するテストケースを新しく書きます。ここで出て欲しい例外は、ArgumentOutOfRangeExceptionですね。

追加仕様を表現するテストコードを追加
//仕様追加: 0以下のときは、例外を出す。
[TestCase]
public void SayTest_ExceptionWhenZero() {
  Assert.Throws<System.ArgumentOutOfRangeException>(() => (new FizzBuzzer()).Say(0));
}

 テストコードを追加したら、予想通りのREDになることを必ず確認します。

REDになり、予想通りのエラーが報告される
CsTdd04.FizzBuzzTest.FizzBuzzerTest.SayTest_ExceptionWhenZero():
  Expected: <System.ArgumentOutOfRangeException>
  But was:  null

 REDになることが確認できたら、製品コードを修正します。

修正した製品コード
public string Say(int n) {
  if (n <= 0)  // ←追加
    throw new System.ArgumentOutOfRangeException(); // ←追加
 
  switch (n) {
    case 3:
    // 以下略

 これでオールGREENになることを確認します。特にリファクタリングは必要なさそうですから、これで仕様追加は完了です。

仕様変更

ある日の昼

レビュアー「あ、bさん! 昨日やった仕様書ですけど」
b君「なんかありました?」
レビュアー「見落としてたんですが、15の倍数のときはFizzとBuzzの間にスペースが入るんです」
b君「もう実装しちゃったよ~」
レビュアー「そういわれても、それが正しい仕様なんで、お願いしますよ」
b君「もぉ、しょうがないなぁ~」(まぁ、即座に直るけどねっ)

 引数が3の倍数かつ5の倍数のときは"FizzBuzz"を返すという仕様でしたが、"Fizz Buzz"(間に半角スペースが入る)に変えてほしいという仕様変更です。

 メソッドの外部設計を変更する場合には、対応するテストケースが必ず存在するはずです。まず、そのテストケースを探します。

仕様変更の対象になっているテストケース(変更前)
[TestCase(15, "FizzBuzz")]

 新しい仕様に従って、テストケースを修正します。

仕様変更の対象になっているテストケース(変更後)
[TestCase(15, "Fizz Buzz")] //スペースが入るのが正しい

 テストコードを変更したら、予想通りのREDになることを必ず確認します。

REDになり、予想通りのエラーが報告される
CsTdd04.FizzBuzzTest.FizzBuzzerTest.SayTest(15,"Fizz Buzz"):
  Expected string length 9 but was 8. Strings differ at index 4.
  Expected: "Fizz Buzz"
  But was:  "FizzBuzz"
  ---------------^

 REDになることが確認できたので、製品コードを修正します。

FizzBuzzの製品コード
public string Say(int n) {
      // 略
    case 15:
      return "Fizz Buzz";  // ←変更
      // 略

 これでオールGREENになることが確認できます。リファクタリングは必要なさそうですから、仕様変更も完了です。

次のページ
仕様変更によって修正が必要になるテストケースの数

修正履歴

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
C#で始めるテスト駆動開発入門連載記事一覧

もっと読む

この記事の著者

biac(ばいあっく)

HONDA R&Dで自動車の設計をやっていた機械屋さんが、技術の進化スピードに魅かれてプログラマーに。以来30年ほど、より良いコードをどうやったら作れるか、模索の人生。わんくま同盟の勉強会(名古屋)で、よく喋ってたりする。2014/10~2019/6 Microsoft MVP (Windows Devel...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6590 2012/05/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング