◆ 手段と目的を取り違えているケース
実は、単に「NUnit」とか「カバレッジ」とか「自動化」とか言ってみたいだけだろって現場も、いまだに多かったりする。
xUnit という道具を、どのタイミングで、どのように使えば、どんな仕組みによって、どんな効用が得られるかを、全然掴まないまま不毛な実践に走るケースがままある。
こういう現場に限って、文字通り取って付けたような後付テストに走って、投下した作業コストに関わる損得もほとんど見えていないまま、目先のコードカバレッジに一喜一憂する。
こうした実りの無い作業が、経験者の意見が届かないプロジェクト外の上層部から強制されたりする現場もたまにあるから恐ろしい。
◆ 「納期が迫ってるからテストコードは後回し」な現場の場合:
ほぼ間違いなく、テスタビリティも同様に後回しになっている。
特に C# の場合、何も考えずにコーディングすると、メソッドのデフォルトが 非virtual という一見ささいな言語の特徴から、テスタビリティが絶望的なレベルにまで落ち込む。
しかもこういう現場では、得てして本体コードに手を入れるリファクタリングは事実上許されていなかったりもする。
こんな状況で、単に順序が違うだけなんて高をくくって、テスト駆動開発がもたらすものと同じ効果を後付テストに期待したところで、数倍のコストをかけて数分の一の効用も得られないという不毛な事に必ずなる。
◆ コードカバレッジによる後付テスト進捗把握の是非:
各クラスを正味の単体でホワイトボックス検証するテストコードならば、迷わずコード・カバレッジで網羅性を測れば良いが、普通は後付テストなんかしてる時点でそんなイイ感じのプログラムには程遠かったりする。
対象クラスの隔離のためのモッキングが活用できるレベルまで、本体コードのテスタビリティが十分に高ければ話は別だが、そうでもない限り後付テストをコードカバレッジで測るのは不合理。(テスタビリティの低さは補助的なツールである程度カバーできるが、C# の場合結構な金が掛かる。)
また、そうした全然モッキングが使えないような低テスタビリティの条件下で後付テストを強行すると、あるテスト対象メソッドの呼び出しが、複数のアーキテクチャ・レイヤを跨いだクラス群の芋づる式のメソッド呼び出しを引き起こす(ItegrationTestなら正にこれが正解だが)。
こうなってしまうと、テスト対象以外のメソッド・コードも含まれてしまうので、正味のカバレッジが全然反映されなくなる。(この他にも、本来のテストの関心とは関係ないデータのセットアップや時間の掛かるサービスの呼び出しを強いられたりするような、様々なテスト・アンチパターンが生じる。)
◆ では、後付テストには価値がないのか
上述のように単体×ホワイトボックスのテストが難しい時は、無理して テストファーストもどきのテストコードを書いてカバレッジを測るよりも、HOW ではなく WHAT に着目して機能テスト(FunctionalTest)を書く法が費用対効果の面で遥かにマシ。
但し、コードカバレッジではなく、機能要件(ユースケース、ユーザストーリ、フィーチャ、etc...)に着目してテスト項目書を起こし、これをベースにカバレッジを把握するべき。
◆ 後付機能テストの効用
テスト駆動開発における ユニットテスト は、第一義的には生産性向上のための手段。
生産性向上の結果として、品質にまわす余力が生じて品質向上が得られるというのは、副産物的としては大いに有りだが、ユニットテストの直接的な効用として品質保証を期待するのは見当違い。
一方、後付の自動 FunctionalTest は、より直接に品質に対して効果を挙げる。
◆ まとめ:
テスタビリティが低いまま、どうしても後付テストを書かざるを得ないときは、
- 適切な境界を定めてブラックボックスの観点でテストすること
- HOW ではなくてWHATに着目し、機能をこそ網羅的にテストすること
- コードカバレッジではなく、機能仕様を単位としたテストコーディングにより網羅性を測ること
- 後付のブラックボックステストなのだから、必ずしも本体と同じ言語にこだわる必要は無い。他のスクリプト言語や 非 xUnit ツールも適宜検討すること
0 件のコメント:
コメントを投稿