TDD Anti-patterns catalogue at Stack Overflow を簡単に訳してみた

Stack OverflowのTDD Anti-patterns catalogueというスレがとても面白かったので訳してみた。


Stack Overflowのvoting機能でアンチパターンへの投票を行っている感じ。
上から投票の多い順になっている。


得票数はこの記事執筆時点(2013.7.9)のもの。
SQLアンチパターンっぽく、パターン名はそのまま片仮名にしてみた。
また、内容がかなり被っているとか、状況がかなりレアじゃないかと思うものは、一部省略しました。

(ブコメで訳間違ってるよ、って教えてもらったので、一部修正しました 2013.7.10)

フリーライド (テストのただ乗り) 50pt

新しいテストケースを書くのではなく、他の機能のテストに新しいアサーションを追加して既存のテストケースに乗っかる。

セカンドクラス シティズン (二等市民) 47pt

プロダクションコードのようにリファクタリングされないテスト。大量の重複やメンテしづらいテスト達。

ハッピーパス 42pt

正常系のハッピーパスだけテストされており、例外や境界値のテストが無い。

ローカルヒーロー (御当地の英雄) 42pt

特定の開発環境に依存したテストケースが存在し、誰かが別の環境で実行するとテストは失敗する。

ヒドゥン ディペンデンシー (隠された依存関係) 42pt

ユニットテストがいくつかのデータが存在する事を前提に書かれており、前提条件が名言されていない。もしデータが適切に準備されていないとテストが落ちる上、適切なエラーメッセージが表示されない。

チェイン ギャング (ギャングの序列) 41pt

あるテストケース同士の組み合わせを特定の順序で実行しなければならない。一つのテストがグローバルな状態(グローバル変数、データベースのレコード)を変更してしまい元に戻さない。
データベースのロールバック漏れ等で良く見られるケース。その他、グローバルな状態を操作する時にtry/catchでラップする事を忘れている場合等にも発生する。

ザ・モックリー (モック過剰) 37pt

テストケースが大量にモックやスタブを含んでおり、実際の挙動では無くモックが返す値をテストしている状態。
(コメントで、レイヤー同士の依存関係が多過ぎる事が原因と考えられるので、リファクタリングしなければいけない状態であると指摘されている)

サイレント キャッチャー (沈黙のキャッチ) 32pt

もし例外が投げられた時に通過して欲しいテストケースがあった場合、その例外が開発者の意図と異なる形で発生してもテストが通ってしまう状態。例えば、期待する例外の型を広く取り過ぎて、意図していない例外もキャッチしてしまっている場合。

アナル プローブ (ケツの穴の検査) 25pt (← Good Naming!!)

あるテストが普通ではなく非常に不健康な方法で実行されている場合。例えば、プライベートなフィールドを読むためにJavaのsetAccesibleを利用したり、クラスを拡張したりテストコードを特定のパッケージに組込む等。このパターンが見られる時は、データを過剰に隠蔽し過ぎている可能性がある。

インスペクター (観察者) 24pt

コードカバレッジを100%にするためにカプセル化の原則を破壊している。

イクセッシブ セットアップ (準備過剰) 23pt

テストケースの事前条件を準備するために、数百行のコードや環境の準備をしなければならない状態。テストにノイズが多くなり本当に検証したい事が分からなくなる。

テスト ウィズ ノーネーム (名無しのテスト) 19pt

バグトラッカー等から書き起こされたテストケースに、具体的な名前が付けられていない状態。例えば'testForBug123'のように。時間が経ってからテストが落ちた時、バグチケットを見るまでその意図が分からなくなる。

スロウ ポーク (のろまなツッコミ) 17pt

ユニットテストの実行が信じられないぐらい遅い状態。開発者はテスト開始をキックした後、トイレに行ったり煙草を吸いにいったりする。ひどい場合は、帰宅する前のその日の終わりにテストを実行する事になる。

インアプロプリエイトリー シェアード フィクスチャー (不適切なフィクスチャーの共有)

複数のテストケースがsetup/teardown処理に必須ではないフィクスチャーを共有している。新しいフィクスチャーを用意するのをサボっている状態。

ザ・ジャイアント (巨人テスト) 15pt

あるユニットテストがめちゃめちゃでかい。実質的に大量のテストケースを含んでしまっている。これは所謂「神クラス」の兆候でもある。テストコード自体にバグが入り込む可能性も高くなる。

ザ・バタフライ (バタフライエフェクト) 14pt

頻繁に変更されるデータを含んだものをテストしなければならないのに、結果を固定値に落とし込む方法が無い状態。例えば現在時刻等を含む構造。出力結果に注意を払わないテストケースになってしまう。

フリッカリング テスト (ちらつき) 13pt

落ちたり落ちなかったりするテスト。特定の時刻ではなく、状態競合等によるもの。典型的には非同期処理に対するテストで発生する。

ウェイト アンド シー (待機、そして観測) 12pt

実行結果を取得するために、一定期間のウェイト処理を挿入し、その後に値を取得するテスト。例えば「Thread.sleep」で待ってから値を確認する等。低スペックの環境や、利用の激しいCIサーバー等でテストが失敗する可能性がある。

フォーティ フット ポール 10pt

テストしようとしているクラスとの結び付きを恐れる余り、過剰な抽象化やレイヤーでロジックを分離しようとする。そのせいで、とても脆く壊れやすいテストになってしまっている状態。

ビリーブ イット ウェン アイ シー (見るまで信じない) 9pt

本当のユーザーのようにテストしようと、無理やりGUI経由でテストを実行しようとする。ビジネスロジックのテストがGUIと結びついていると、GUIの変更で数多くのテストケースが破壊されてしまう事になる。

エンヴァイラメンタル ヴァンダル (環境の侵略者) 9pt

テスト実行のために、環境変数や特定のTCPポート等が必要になる場合。利用できないポートがある時はテストが失敗する。テストで利用するポート番号等がハードコードされていると、同時に複数環境向けのテストを実行した時にテストが失敗する事になる。

スリーパー (休火山) 9pt

未来のある日時が訪れた時に失敗してしまうテスト。日付やカレンダーに関わるロジックで発生する。
「このコードは2000年より前に書き直されるだろう」 1960年代の多くのプログラマーの言

カッコー (カッコウの鳴き声) 9pt

あるテストケースが他のいくつかのテストケースに依存している状態。他のテストと同じsetupメソッドを使っているにも関わらず、その成果物を捨てている。
インアプロプリエイトリー シェアード フィクスチャーの一例。

チューリング テスト 8pt

なんらかの効果なツールが魔法のように自動生成したテストケースが多数存在する。

デッド ツリー 8pt

スタブが生成されているが、そのコードの実装が無い。

ウェット フロア 5pt

テストが生成したデータがどこかに保存され、テストが終了した時に適切にクリーンアップされていない状態。テストを続けて実行すると失敗する可能性がある。例えば、tempディレクトリにファイルを保存するようなテストを別々の実行ユーザーで実行した時、パーミッションの問題で適切にデータが削除されない事があり、テストが壊れてしまう。