谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

xUnit成熟度モデル 〜あなたの組織はどのレベル?

本エントリーは、Software Test & Quality Advent Calendar 2011の10日目です。
http://atnd.org/events/22833


前の9日目は @m_seko さんの
「負荷テスト対象のWebアプリがこういう非機能要件(+α)を備えていたらいいのにという願望」です。
http://d.hatena.ne.jp/sekom/20111209


普段、品質やテストなどには興味なさそう(?)にしている私ですが、
たまには、エンジニア視点から、テストについて語ってみましょう。

xUnit成熟度モデルって?

xUnit成熟度モデルとは、
組織がxUnitをより適切に利用できるようになることを目的として
遵守するべき指針を体系化したものである。


あわせて読みたい : 能力成熟度モデル統合 (CMMI) - Wikipedia


正味の話で言うと、僕がJUnitに初めて出会ってから今に至るまで、
どのようにJUnitを使い、失敗し、改善して行ったのかを、段階ごとに振り返った軌跡です。

レベル1 : 初期

xUnitを利用しているが、記述粒度、記述方針や、利用プロセスなどを決めておらず
それぞれのエンジニアが、自分の裁量でテストコードを書いている。


このレベルの典型的な問題

  • assert文がなく、目視で結果を確認するテストコードが多い。
  • テスト実施前に手動準備が必要である。しかし、その手順がどこにも記載されていない。
  • なぜかxUnitを使っていないテストコードもある。
  • テストコードがバージョン管理されていない。
  • テストコードをバージョン管理しているが、ほぼエビエンス代わりであり、まず再テストは通らない。


次のレベルに向けた活動

  • xUnitの利用方法について、組織内・プロジェクト内での勉強会を行ない、レベル感を合わせる。
  • 組織、プロジェクトとして、どの工程でどのようにxUnitを利用するかを、事前に決める。

レベル2 : 過剰に書かれた

開発プロセスにてxUnitの利用方法を規定している。
ただし、過剰にテストしてしまったり、テストデータ量を爆発させたり、
xUnitが向いてないテストまで無理にxUnit化するなどするため、テスト工数がこれまでよりも掛かっている。


このレベルの典型的な問題

  • 手動でテストしていた時に比べて、テスト工数が2倍以上に増えている。
  • テストコードが、本体コードと同程度〜2倍程度の規模にまで膨らんでいる。
  • Excel形式の投入データ、検証データが大量にあって、レビューも修正もできない。
  • カバレッジ100%を達成するべく、特に最後の10%のためにテスト工数の半分を消費している。
  • テストコードをバージョン管理しているが、膨大すぎてメンテナンスできず、再テストが通らない。

これらは、xUnitを始めた者が、一度は必ず陥る暗黒面だと言える。


次のレベルに向けた活動

  • 小さな部分を、小さくテストする文化を浸透させる。
  • 設計時や実装時に、テスト容易性を考慮した設計を行う。
  • モックを利用したテストを取り入れる。

レベル3 : モック化された

過剰なテストへの対策として、「小さな範囲を小さくテストし、積み重ねる」ために、モックを利用している。


モックを実現する方法として、設計・実装を工夫する(protectedメソッドの活用など)か
モックライブラリ(djUnit、Mockitoなど)を利用するかは問わない。


いずれの方法を使っていても、モックを使う事でテストをスリム化することができ、
テスト工数や、メンテナンスコストを削減することができている。


このぐらいのレベルから、テストの事前準備自体をテストコード内で記述しているため、
リポジトリからソースを取得してビルドするだけで、すぐにテストを実行できるようになっている。


このレベルの典型的な問題

  • モックライブラリの罠に陥っている
    • カバレッジ計測ツールの相性が悪く、期待するカバレッジ結果を算出できない。
    • 逆に可読性の低いコードになってしまい、他の開発者がメンテナンスできない。
  • 本体にバグがあっても、テスト自体がうっかり通ってしまっていて、問題に気付けない。
  • 気がついたら、モック自体をテストしている。


次のレベルに向けた活動

  • モックライブラリを使わずともモック化しやすいような設計・実装を浸透させる。
    • 継承ではなく委譲
    • メンバ変数よりも引数
    • ステートレス化
    • protectedメンバ、protectedメソッドの活用

レベル4:継続的に実施された

CIツールなどを導入して、ビルドとxUnitを定期的に実施している。


CIツールを導入することで、テストコードのメンテナンスを行う習慣が浸透するほか、
テスト環境に依存しない、テスト環境を壊さないようなテストコードを作成するようになっている。


このレベルの典型的な問題
CIツールに対して過剰な安心感を持ってしまい、これまで気付けた問題に気付けなくなる。


たとえば、テスト全体ではなく、一部のテストのみを定期的に実行している場合で
「CIしているから大丈夫」と考えて、動作確認を疎かにしてしまいバグを埋め込んでしまう。


CIツールは「安心」のための「シートベルト」に例えられることがあるが、
シートベルトをしていれば時速200kmで峠を攻めても良い、というわけではない。

レベル5 : 最適化している

テストコードを書くポイントや、分量などのバランスが分かり、
最適なテストコードを書くようになる。
もちろん、組織やプロジェクトの性質によって「最適」の定義、観点は異なっている。


参考までに、観点や選択肢を、いくつか列挙しておく。

  • 単体テスト対象の考え方
    • あくまで単一メソッドのテストを行ない、外部メソッドは全てモック化している
    • 原則としてpublicメソッドをテスト対象と考え、ある程度のまとまりごとに試験する
  • 外部システムとの連携
    • データベースへのデータ投入や外部システム操作を、テストコード内で実施する
    • データベース部分や、外部システム連携箇所は、すべてモック化する
  • モックの考え方
    • モックライブラリを使いこなす
    • モックライブラリは禁止して、ライブラリなくモック化できるよう設計する

まとめ

  • レベル1:xUnitを使っているが、テスト自体が杜撰である
  • レベル2:テストコードが過剰である
  • レベル3:モックを使っている。
  • レベル4:CIで定期実行している。
  • レベル5:組織として、最適な解を選択している。


割と好き放題に書いてきましたが、いかがでしたか?
また、あなたの組織は、どのレベルでしたか?


もしこのエントリがあなたの組織のxUnitレベルが上がる一助になれば、幸いです!(><)