プログラマでありたい

おっさんになっても、プログラマでありつづけたい

テストのデータ生成は、FixtureよりFactoryモデル

python project metrics through hudson
 ブログからコードの匂いがしなくなってきたので、たまには開発論の話をしてみます。最近では、当たり前のようにテストのコードが書かれるようになってきて、時代が変わってきたなぁと嬉しくなります。しかしユニットテストを見ていると気になる事があります。それは、データベース関連のテストをする際に、事前にテストデータを入れ込んだDBでテストしているパターンです。いわゆるFixture(フィクスチャ)と呼ばれる手法です。


 Fixtureの便利な点は、テストデータの準備が非常に楽という点にあります。例えば、テスト用のDBにsqliteを使っているのであれば、事前にデータを入れておいたsqliteを用意しているだけで済みます。mysql等を使う場合でも、データを用意しておいてインポートするだけで良いでしょう。非常にお手軽に思えます。
 では、欠点は何でしょう?テストコードがデータに依存し過ぎて、やがてDBのデータを変更出来なくなるという点です。どういうことでしょうか?例えば、とあるテーブルに100件くらいのデータを入れていて、そのデータを元に10件くらいのテストメソッドがあったとします。そして、新規メソッドを追加して、更にテストデータのパターンを追加する必要が出たとしましょう。何が必要でしょうか?追加したテストデータが、既存のテストに影響を与えないように注意する必要が出てきます。例えば、データが100件あるという前提での境界値テストをしていないか等ですね。100件×10件くらいだったら何とかなりますが、それが1,000件のテストコードだったら、どうでしょう?依存性を考えると、メンテナンスする気がしませんね。またN*Nのパターンでテストが必要な、関連モデルのテストもデータ作るのが面倒臭いですね。


 では、どうすれば良いのでしょうか?その解の1つに、Factory(ファクトリー)モデルがあります。これは、テストごともしくはテスト群ごとにコードからデータを生成するパターンです。メリットとしては、前述のFixtureの欠点であったデータのメンテナンス性を大幅に向上させ、かつデータの依存性を小さく出来ます。デメリットとしては、データ生成の為にコードを書くので記述量は増えます。しかし、記述量の問題は、補助ライブラリを使うことにより負担にならない程度に減らせます。Railsであれば、Factory girlが有名ですね。


 ちなみにFixtureですが、まったくダメな子という訳では決してありません。例えば、UI層のテストを書く場合であれば、Fixtureを使った方が便利な場合も多いです。要は使い分けですね。テストデータの生成方法1つをとっても拘りやノウハウがあるので、色々考えてみてください。Enjoy!!


See Also:
Web画面の自動テストの導入に失敗する理由とその対策
Selenium2.0 WebDriverで複数ブラウザのUIテスト もう一度、Selenium再入門
JenkinsとSelenium WebDriverでUI層のテストも自動化&永続化する