« [TDD の練習(4)] フィボナッチ数列の問題 ~ その1 : 数列を生成する | トップページ | [VS2010] GUI のテストも、 ユニットテストで »

2009年1月12日 (月)

[TDD の練習(4)] フィボナッチ数列の問題 ~ その2 : 偶数だけを集計する

前回で 「フィボナッチ数列発生機」 が出来上がりました。
こんどは、 生成されてくるフィボナッチ数列から偶数を選び出して集計してくれるモノ 「フィボナッチ数列偶数集計機」 を作ります。

フィボナッチ数列発生機の使い方は、 そのテストコードを見れば分かりますね。 また、 テストコードには、 n=45, F(n)=1836311903 まで計算できると示されていますから、 設問の 400万までを計算するのに問題は無いこともわかります。

いつものように、 どんなテストコードを書いていけばいいのかを、 文章で書いてみますので、 ユニットテストに書き下してみてください。
ところで、 設問では合計値だけが要求されています。 そのときの n やフィボナッチ数が幾つだったかは不要なのです。 ですが、 気になりますよね?
製品コードには含まれないけど、 テストのときだけ検証したい値があるときはどうするか? そのためのテストテクニックのひとつも、 ご紹介します。

あ、 n=10 までのフィボナッチ数と、 その偶数・奇数、 そして偶数の合計の表を載せておきますね。 これを先に作っておかないと、 テストを書けませんもの。

             番号 n = 1, 2, 3, 4,  5,  6,  7,  8,  9, 10, ...
フィボナッチ数列 F(n) = 1, 2, 3, 5,  8, 13, 21, 34, 55, 89, ...
                偶奇 = O, E, O, O,  E,  O,  O,  E,  O,  O, ...
                合計 = 0, 2, 2, 2, 10, 10, 10, 44, 44, 44, ...

  1. limit=1 のとき ( F(n) が 1 を超えないとき )、集計結果は 0

  2. limit=2 のとき、偶数は 2 だけなので、集計結果は 2
    → 集計するロジックを実装してみる
     
  3. 確認テスト。 limit=3 のときも、2。 limit=33 のとき 10で、 limit=34, 35, 89 のときは 44。

  4. 本番: 数列の項が400万を超えない範囲で、偶数の項の総和を求めよ。
    → 適当な期待値で走らせて、 Assert() のエラーメッセージから正解を得て書き換える。

  5. 本番の時の、 最後の n と F(n) は幾つか? F(n) は 400万を超えていないはずだよねぇ?
    → 製品コードでは不要だけど、 テストの時には確認したい。 #if DEBUG を利用して、 プローブ (探針) を仕込む。
    → 4. と同様に、適当な期待値で走らせて、 エラーメッセージから正解を得る。

回答例 ( C# + NUnit 用のソースコード ) はこちら → FibonacciSequenceEvenNumberTotalizerTest.cs [3KB]

ちゃんと自分で書いてみてから、 見てくださいね f(^^;

そして、 このテストコードをパスするように実装とリファクタリングしたコードは、 こうなりました。

namespace フィボナッチ数列 {
  public class フィボナッチ数列偶数集計機 {
    public static int 集計しろ(int limit) {
      int sum = 0;

      foreach (int フィボナッチ数 in フィボナッチ数列発生機.Getフィボナッチ数列()) {
        if (フィボナッチ数 > limit)
          break;

        if (IsEven(フィボナッチ数))
          sum += フィボナッチ数;

#if DEBUG    // (5) で追加したプローブ
        フィボナッチ数列偶数集計機._test_lastN++;
        フィボナッチ数列偶数集計機._test_Fibonacci = フィボナッチ数;
#endif
   
      }

      return sum;
    }

    private static bool IsEven(int f) {
      return (f % 2) == 0;
    }

    // (5) での実装 (プローブ)
#if DEBUG
    [System.ThreadStatic()]
    private static int _test_lastN;

    [System.ThreadStatic()]
    private static int _test_Fibonacci;

    public static void Testカウンタをリセットしろ() {
      フィボナッチ数列偶数集計機._test_lastN = 0;
      フィボナッチ数列偶数集計機._test_Fibonacci = 0;
    }

    public static int TestGetLastN() {
      return フィボナッチ数列偶数集計機._test_lastN;
    }

    public static int TestGetLastFibonacci() {
      return フィボナッチ数列偶数集計機._test_Fibonacci;
    }
#endif

  }
}

|

« [TDD の練習(4)] フィボナッチ数列の問題 ~ その1 : 数列を生成する | トップページ | [VS2010] GUI のテストも、 ユニットテストで »

プログラミング」カテゴリの記事

-プログラミング ( わんくま )」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/209349/43722399

この記事へのトラックバック一覧です: [TDD の練習(4)] フィボナッチ数列の問題 ~ その2 : 偶数だけを集計する:

« [TDD の練習(4)] フィボナッチ数列の問題 ~ その1 : 数列を生成する | トップページ | [VS2010] GUI のテストも、 ユニットテストで »