NUnitでBDD - サピア・ウォーフの仮説は当てはまらないが。(-.-)

NAgiler2006-02-02


TDDをはじめて間もない頃に、ボトムアップで設計しているうちは良いのだが、トップダウンで設計しようとしたりクラスをまたがったテストを書こうとした矢先にどのようにテストすればよいかが分からなくなって立ち往生した経験はないだろうか。

これは実装クラスとテストクラスの関係が1対1であることに慣れすぎてしまっていることが原因だ。テストとして考えずにビヘイビアの側面として捉えるような視点に移行してみればおのずと状況は変わってくる。

私は最近、NUnitでBDD的なテスト(ビヘイビアと呼びたいところだが、サピア・ウォーフの仮説が当てはまらないNUnitではテストという呼び方に甘んじておこう)を書く試みを行っている。以下にその命名規則を示そう。これらは全て日本語で名前付けを行う。

  • テストアセンブリ → ソリューション名.Behaviours
  • 名前空間 → [ソリューション名.Behaviours].ストーリー名
  • テストクラス → コンテキスト名
  • テストメソッド → スペック名

この命名規則に則って名前づけを行ったStackのサンプルでは、NUnit.GUIのツリーに表示される内容はこんな感じになる。

  • BDDSample
    • Behaviours
      • Stackのストーリー
        • nullをプッシュする
          • IsEmptyがfalseであるべき
          • Topを呼び出して返された値がnullであるべき
          • オブジェクトをポップすると返された値がnullであるべき
        • オブジェクトを1つプッシュする
          • IsEmptyがfalseであるべき
          • Topを呼び出してもIsEmptyがfalseであるべき
          • オブジェクトをポップするとIsEmptyがtrueになるべき
          • プッシュしたオブジェクトとTopを繰り返し呼び出して返されたオブジェクトは全て同じであるべき
          • プッシュしたオブジェクトとTopを呼び出して返されたオブジェクトは同じであるべき
          • プッシュしたオブジェクトとポップしたオブジェクトは同じであるべき
        • 複数のオブジェクトをプッシュする
          • Topを呼び出して返されたオブジェクトは最後にプッシュしたオブジェクトと同じであるべき
          • それぞれをポップするとそれらが正しい順番で削除されるべき
        • 要素を含んでいない
          • IsEmptyがtrueであるべき
          • オブジェクトをポップするとInvalidOperationExceptionが発生すべき
          • Topを呼び出すとInvalidOperationExceptionが発生すべき

このように、NUnit.GUIのツリーを見るだけでStackがどんな振る舞いをするかが一目瞭然だ。

また、Stackのストーリーの次の階層がテストクラスになるわけだがこれを見れば1つのクラス(Stack)に対してコンテキスト毎に分割されたテストクラスが複数存在していることもわかるだろう。