【しばらく編集不可モードで運営します】 編集(管理者用) | 差分 | 新規作成 | 一覧 | RSS | FrontPage | 検索 | 更新履歴

TddAntiPatterns - TDD のアンチパターン

目次

TDD のアンチパターン

この文書について

TDD のアンチパターン

少し前から TDD のアンチパターンのことを書きはじめた。 中でも "現実に" よくあるものからざっと書き出して、 それから yahoogrouptestdrivendevelopement メーリングリストに 投稿してみた。するとすばらしいフィードバックの数々を受けることができた!

なお、これは現時点での一覧にすぎない点に留意してほしい。 これから拡大していければいいと思う。

TDD アンチパターン・カタログ

嘘つき (The Liar)

全テストケースがパスして正しいように見えるテスト一式なのに、 よく見ると本当は意図したものを何もテストしていないことに気付く。

セットアップ過多 (Excessive Setup)

テスト開始に大量のセットアップを要求するテスト。 テストひとつの環境をセットアップするのに数百行をも要することもある。 関係するオブジェクトが複数あり、どれがテスト対象なのかを判別するのも難しい。 セットアップでの "雑音" が多すぎるからだ。

巨人 (The Giant)

たしかにオブジェクトを正しくテストしているものの、 一つの単体テストが数千行、大量のテストケースを含むテスト。 これはテストしているシステムが God Object である兆しだ。

モック酔い (The Mockery)

モックを使うのが手頃で良い場面もある。 しかしテストしないオブジェクトをモック化して除外するのに 開発者がハマってしまうことがある。 こうなると、単体テストは大量のモックやスタブを含んでしまう。 そして肝心なシステムがテストされず、 モックの返す値がテストされるような倒錯がおきてしまう。

検査官 (The Inspector)

単体テストがコード網羅率 100% を目指しカプセル化に違反してしまう。 中の出来事を知り過ぎているせいで、リファクタリングで既存のテストが壊れてしまう。 何を変更するにも単体テストを直さなければいけない。

太っ腹な残り物 (Generous Leftovers)

テストで作られたままどこかに残ってしまったインスタンス。 別のテストが抜け目なくそれを再利用しており、 「作り手」が後ろに回ったりいなくなると、そのデータを使うテストは軒並失敗する。

地元の英雄 (Local Hero)

テストが書かれた環境固有の何かに依存している。 結果としてテストは開発機でしか動かず、他所で動かそうとすると失敗する。

小姑 (The Nitpicker)

本当はごく一部しか関係がないはずの出力結果を、全てチェックする単体テスト。 瑣末事に合わせてテストを更新しなければいけなくなる。 ウェブアプリケーションのテストでよくある。

秘密のキャッチ (The Secret Catcher)

アサーションがなく、何もチェックしていないように見えるテスト。 しかし「神は細部に宿る。」 実は失敗すると投げられる例外にテストが依存している。 テストのフレームワークが例外をキャッチし、失敗として報告してくれるのを期待している。

ペテン師 (The Dodger)

細かい(従ってテストしやすい)副作用ばかりをいくつもテストしながら、 肝心な期待動作を確認しない単体テスト。 データベースのテストでみかけることがある。 メソッドを呼んでデータベースを select し、その結果にアサーションをする。

大声 (The Loudmouth)

テストが通っているにも関わらず、診断、 ログその他のうるさい出力でコンソールを乱す単体テスト。 テストの作成中に出力を目で見たいことはある。 しかしもういらないのに、そのまま放置されている。

はらぺこキャッチ (The Greedy Catcher)

例外をキャッチして握りつぶし、わかりにくい失敗メッセージに替えてしまうもの。 更には単にそれをログに書き(「大声」参照)、そのままテストを通してしまうものもいる。

序列屋 (The Sequencer)

順序のないリスト (unordered list) の中味が いつも同じ順番であることにアサーションが依存している単体テスト。

隠れ依存 (Hidden Dependency)

「地元の英雄」の近い親戚。 以前なにかで作ってしまった既存のデータが必要な単体テスト。 データがないとテストは失敗し、開発者には何がなぜ必要なのかという情報をほとんど残さない。 開発者は広大なコードの中で期待されているデータがどこにあるのか探す羽目になる。

点呼 (The Enumerator)

テスト名が数えあげになっている単体テスト。test1、test2、test3 みたいの。 テストケースの意図が不明確で、それを知るにはコードを読んで祈るしかないという。

異邦人 (The Stranger)

その単体テストに所属していないテストケース。 それがテストしているのは別のオブジェクトで、 本来テストすべきオブジェクトに使われるオブジェクトという場合が多い。 肝心のテストケースはどこかに行ってしまって、 テストすべきオブジェクトの出力を使わず他のオブジェクトの挙動を 直に使っていたりする。「遠くの親戚(The Distant Relative)」としても知られる。

OS のエバンジェリスト (The Operating System Evangelist)

特定 OS の環境に依存した単体テスト。 わかりやすい例としては Windows の改行コードを使ったテストケースがある。 Linux で動かした時だけ失敗する。

奇跡的成功 (Success Against All Odds)

どちらかと言えば、失敗より成功を優先して返すように書かれたテスト。 失敗すべき場合にも成功してしまう悲しい副作用がある。

タダ乗り (The Free Ride)

別々の機能について新しいテストケースを書くかわりに、 既存のテストケースにアサーションを追加で乗せていくこと。

ザ・ワン (The One)

複数のパターン、特に「タダ乗り」と「巨人」の組合せ。 テストメソッドが一つだけで、それがオブジェクトの全ての機能をテストしている単体テスト。 一つの目安としては、テストメソッドが単体テストと同じ名前を持っていること。 それに複数行のセットアップとアサーションがあること。

覗き魔 (The Peeping Tom)

共有資源を使って他のテストの結果を覗き、テストするシステムが完全に正しく動いているのに 失敗してしまうようなテスト。これは fitnesse を使っているとよく起こる。 fitnesse では静的メンバ変数に保持したコレクションが終了時に解放されない。 そのせいで他のテストを動かす時に意図せず飛び出してくる。

のろまな動き (The Slow Poke)

動作がひどく遅い単体テスト。実行すると風呂に入って一服できたり、 もっと酷くなると一日の終わり、帰宅前に動かすようになってしまったもの。

さて、今回はこんなところにしておこう。 ここにリストしたものからトップテンを投票してもらえればと思う。 それらについて詳しく内容や、例、症状、 あと(できれば)アンチパターンを撃退するリファクタリングについて書いてみたい。

誰かの話をとりこぼしていたら教えてほしい。それと更なるパターンも大歓迎!

コメント