SHOEISHA iD

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

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

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

TDDしにくいモノは切り離せ! ~ 現在日時の扱い方

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

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

ダウンロード CsTdd06.zip (10.7 KB)

応用2: 現在時刻プロパティのインターフェースを定義して使い分ける

 本来の実装と、テスト用実装を切り分けるために、インターフェースを導入します。

製品コード: 現在時刻プロパティを提供するインターフェース
public interface ISystemClock {
  DateTimeOffset 現在時刻 { get; }
}

 現在時刻プロパティの部分を、このインターフェースを実装するように変更します。

テストコード: インターフェースを実装しているか?
[TestCase]
public void InterfaceTest() {
  var clock = new SystemClock();
  Assert.IsInstanceOf<ISystemClock>(clock);
}
製品コード: インターフェースを実装する現在時刻プロパティ
public class SystemClock : ISystemClock {
  public DateTimeOffset 現在時刻 {
    get {
      return DateTimeOffset.Now;
    }
  }
}

 現在時刻をフォーマットするメソッドは、ISystemClockインターフェースのオブジェクトを利用するようにします。その方法としては、UnityなどのDIコンテナーを使うこともできますが、ここでは簡単のためにメソッドの引数として渡すことにします。

製品コード: ISystemClockを使って現在時刻の文字列を得る
public static string Getフォーマット済み現在時刻(ISystemClock systemClock) {
    return systemClock.現在時刻.ToString("hh時 mm分 ss秒");
}

応用2-1: SystemClockのダミーを自作する

 ISystemClockインターフェースの実装は、可能ならば自前でダミーを作ってしまうと確実です。ここでも省略しますが、ダミーのためのユニットテストを書いてから、それを通すように次のようにテストプロジェクト側に実装を作ります。

テストコード: ISystemClockを実装するダミークラス
public class SystemClockDummy : ISystemClock {

  internal DateTimeOffset テスト用_現在時刻 { get; set; }

  public DateTimeOffset 現在時刻 {
    get { return テスト用_現在時刻; }
  }
}

 このダミークラスを使って、ユニットテストを記述します。

テストコード: ダミーを使ってテスト
[TestCase]
public void Getフォーマット済み現在時刻Test_自作ダミーを使う() {
  var givenTime = new DateTimeOffset(new DateTime(2012, 8, 8, 14, 3, 0));

  var clock = new SystemClockDummy(){ テスト用_現在時刻 = givenTime, };
  Assert.AreEqual("14時 03分 00秒", Class3.Getフォーマット済み現在時刻(clock));
}

応用2-2: SystemClockのモックを使う

 ダミーを作るのが難しい場合には、モックオブジェクトを使います。モックは、そのテストに必要な挙動だけを定義すればよいので、複雑なダミーを作るよりはシンプルに書くことができます。その反面、挙動が変更になった時には、関連するすべてのテストでモック生成部分の修正が必要になります。

 ここでは、NUnit付属のNSubstituteを使ってみましょう。NUnit 2.6をインストールした場合には、システムドライブの\Program Files (x86)\NUnit 2.6\bin\libフォルダーにNSubstitute.dllが入っているので、テストプロジェクトの参照設定に追加します。テストコードには、using NSubstitute;を追加します。すると、次のようにテストコードが書けます。

テストコード: モックを使ってテスト
[TestCase]
public void Getフォーマット済み現在時刻Test_モックを使う() {
  var givenTime = new DateTimeOffset(new DateTime(2012, 8, 8, 14, 3, 0));

  var clock = Substitute.For<ISystemClock>();  //モックオブジェクトを生成
  clock.現在時刻.Returns(givenTime);  //テストに必要な挙動だけを定義

  Assert.AreEqual("14時 03分 00秒", Class3.Getフォーマット済み現在時刻(clock));
}

まとめ

  • 制御しにくいものは切り離せ! 手動でテストしなければならないコードを、できるだけ少なくしよう。
  • 制御しにくい部分に、#if ディレクティブを使ってテスト用の実装を埋め込む方法。簡便だが、製品コードが汚くなる。
  • 制御しにくい部分のダミーを自作する方法。複雑な場合は、作るのがたいへん。制御しにくい部分の仕様が変わった時には、ダミーを修正すれば済む。
  • 制御しにくい部分をモックで代用する方法。テストを書くときは、とても楽。制御しにくい部分の仕様が変わった時には、テストコードの修正箇所が多くなるので、修正漏れに注意。
  • 緊急避難的に、Visual Studio 2012の上位版に正式搭載されるFakesのシムを使うことも。テスト時間が長くなるし、テスタビリティに欠ける設計をしているということであるから、TDDでは避ける。後付けでテストを作る際には有用。

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

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

もっと読む

この記事の著者

biac(ばいあっく)

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

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング