2015年7月27日月曜日

オニオンスライスのオートメーション

ふだん単体テストのオートメーションにあまりなじみのない方のために、少し具体的な話をしてみようと思います。
そして例によって具体例は先週の続きです。
以下のレコードをデータベースから取得して画面に表示するためのコンテキストをテストします。

<朝食>
     <食べたものリスト>
          <食べたもの>トースト</食べたもの>
          <食べたもの>ハムエッグ</食べたもの>
          <食べたもの>ひよこ豆とレタスとトマトのサラダ</食べたもの>
     </食べたものリスト>
     <飲み物>コーヒー</飲み物>
</朝食>

1)まずは、期待値を構成します。
listと飲み物はprivateスコープです。
var expected = new 朝食();

このオブジェクトはコンストラクタの中で次のように初期化されます。
this.list = new 食べたものリスト()
list.Add( new 食べたもの("トースト") );
list.Add( new 食べたもの("ハムエッグ") );
list.Add( new 食べたもの("ひよこ豆とレタスとトマトのサラダ") );
this.Set飲み物 ( "コーヒー" );

2) 次に被検クラスを起動して、返される値をキャッチします。
var target = ある朝に食べた朝食() ;
朝食 actual = target.Find();

3)最後に期待値と実測値が同じであるか判定します。
for ( 朝食 a : actual ) {
     for ( 朝食 e : expected ) {
          assertEquals( e.Get食べたもの, a.Get食べたもの );
          assertEquals( e.Get食べたもの, a.Get食べたもの );
          assertEquals( e.Get食べたもの, a.Get食べたもの );
     }
}
assertEquals( expected.Get飲み物, actual.Get飲み物 );

ここではじめてに期待したオブジェクトとデータベースから返却された実測値が同一であること、つまり、期待に沿ったものであるかを判定しています。
assertでかかれた比較がイコールで結ばれればテストは成功なので、グリーンシグナルとなるわけです。
ただし、正確に言うと、Listは投入された要素の順番が保証されないので、ここはもっと別の記述になるはずですが、テストの流れをシンプルにご紹介するために、あえてこのように書きましたことを注意してください。

こうやって見てみると意外と簡単ですね。
とは言え、このテストではデータベースに直接接続していますから、本来はもっと工夫が必要ですし、これでは不充分です。
加えて仕様が変化したときに、当然、このテストコードでは整合しなくなるわけですから、もっと柔軟な展開も頭の中に入れておかなければなりません。
と、いろいろ考えることは多々ありますが、それでも、この方法には価値あることが少なからずあると思います。
それを知るには実際的な体験が必要です。

よくテストコードのメンテナンスが大変だ、という意見も聞かれますが、それはテストとしての構造設計がうまくできていないことに原因があることが大半です。
変化に強い実装コードのノウハウは、そのままテストコードの柔軟性にも同じように展開できるはずです。平面的な構造設計だけでは、そもそも実装コードのメンテナンスもままなりません。ぜひ、このような視点に注意を払って挑戦してみてください。
そこではじめて単体テストのオートメーションの価値に気がつくと思います。

0 件のコメント :

コメントを投稿