Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

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

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

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2012/08/24 14:00

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

 TDDを実際のプログラミングに使い始めると、テストファーストしずらい場合があることに気がつきます。テストファーストというより、とにかくユニットテストが書きにくい、そんなパターンに外部依存があります。今回は、現在日時の扱い方を例に、外部依存への対策を考えてみましょう。

目次

はじめに

 プログラムの外部に依存している部分は、ユニットテストが書きにくいものです。ファイルやデータベースへのアクセスなどは、まだなんとかなります。面倒ではありますが、ユニットテストから制御してやればよいのです。そうできない場合はどうしたら良いでしょう? 基本戦略は、「制御できないモノは切り離せ!」です。

 今回は、PC内蔵のシステムクロックに依存するコードを例にして、その戦略を考えてみます。

対象読者

  • TDDに興味をお持ちの.NET Frameworkの開発者。

必要な環境

 サンプルコードを試してみるには、C# 2010(Expressで可)とNUnit 2.6が必要です。本稿執筆時点では、下記から入手できます。

C# 2010 ExpressとNUnitの入手先、およびNUnitのインストール手順

※ Visaul Studio 2012 RC/RTMでも構いません。その場合は、Visual StudioのIDEとNUnitを統合できます(『Visual Studio 11 betaの単体テスト機能を使ってみよう!』を参照)。

ユニットテストがうまく書けないコード

【製品コードの仕様】現在時刻を返すプロパティ
返値 string型
現在時刻を"HH時 mm分 ss秒"というフォーマットで返す(24時制)。

 製品コードは、あっさり書けます。

製品コード: 現在時刻をフォーマットして返す
public static string フォーマット済み現在時刻 {
  get {
    return DateTimeOffset.Now.ToString("hh時 mm分 ss秒");
  }
}

 このプロパティをテストするコードは、どのように書けば良いでしょう? 例えば、こんなふうでしょうか…?

テストコード: これではテストにならない!
[TestCase]
public void Getフォーマット済み現在時刻Test_これではダメ() {
  var expected = DateTimeOffset.Now.ToString("hh時 mm分 ss秒");
  var result = Class1.フォーマット済み現在時刻;

  Assert.AreEqual(expected, result);
}

 これではテストになっていませんし、ごくわずかですがテストが想定外の失敗をする可能性もあります。

 テストの期待値expectedを実装と同じコードで作っていますが、これでは同語反復です。テストの意味がありません。実際、この実装にはバグがあるのですが、発見できません。また、このテストはほとんどの場合でGREENになりますが、expectedの算出とresultの取得の間に運悪く秒が変わってしまうとREDになってしまいます。

緊急避難: Fakesのシムを使う

 Visual Studio 2012の上位版に正式搭載されるFakesのシムを使うと、製品コードはそのままで、DateTimeOffset.Nowから返される値を任意に制御することができます。ただし、テストの実行時間が桁違いに長くなりますので、緊急避難的な対応だと考えてください。詳しくは『Visual Studio 11 betaの単体テスト機能を使ってみよう!』をご覧ください。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • biac(ばいあっく)

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

バックナンバー

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

もっと読む

All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5