自己テストコード
2014年5月1日
「自己テストコード」とは、私がリファクタリングの中で使用した用語で、機能的なソフトウェアと同時に包括的な自動テストを作成する実践を指します。うまく行けば、単一のコマンドを呼び出すことでテストを実行でき、これらのテストによってコードに潜むバグを明らかにできるという確信を持つことができます。

私は最初にOOPSLAカンファレンスで"Beddara" Dave Thomasの話を聞き、この考えに遭遇しました。彼は、すべてのオブジェクトは自身をテストできるべきだと述べていました。私は突然、コマンドを入力するだけで、ハードウェアのメモリテスト(ブート時に見られたもの)のように、私のソフトウェアシステム全体が自己テストを行うというビジョンを思い浮かべました。すぐに私は自分のプロジェクトでこのアプローチを探求し始め、その利点に非常に満足しました。数年後、Kent Beckと協力して作業を行い、彼も同じことを行っていることを発見しました。ただし、私の方法よりもはるかに洗練された方法でした。これは、Kent(とErich Gamma)がJUnit(自己テストコードとその姉妹であるテスト駆動開発の多くの考え方と実践の基盤となったツール)を作成する少し前でした。
コードベースに対して一連の自動テストを実行し、テストがパスすればコードに重大な欠陥がないという確信を持てる場合、自己テストコードを持っています。私が考えている方法の1つは、ソフトウェアシステムを構築するのと同時に、システム内の欠陥を検出できるバグ検出器を同時に構築することです。チームの誰かが誤ってバグを導入した場合、検出器が作動します。テストスイートを頻繁に、少なくとも1日に数回実行することで、バグが導入されてすぐに検出できるため、最近の変更を確認するだけで済み、はるかに簡単にバグを見つけることができます。動作するコードと、その動作を維持するためのテストがないプログラミングエピソードは完了しません。私たちの姿勢は、テストのない重要なコードは壊れていると仮定することです。
自己テストコードは継続的インテグレーションの重要な部分であり、実際、自己テストコードがない限り、継続的インテグレーションを真に実行しているとは言えません。継続的インテグレーションの柱として、継続的デリバリーにも不可欠です。
自己テストコードの明白な利点の1つは、本番ソフトウェアに侵入するバグの数を大幅に削減できることです。その中心にあるのは、開発者がコードとテストを同時に記述することを自然に考えるテスト文化を構築することです。
しかし、最大の利点は、単に本番バグを回避することではなく、システムに変更を加えることができるという自信です。古いコードベースはしばしば恐ろしい場所で、開発者は動作中のコードを変更することを恐れています。バグを修正することさえ危険になる可能性があります。なぜなら、修正するよりも多くのバグを作成する可能性があるからです。このような状況では、新しい機能を追加する速度が非常に遅くなるだけでなく、システムをリファクタリングすることを恐れるようになり、技術的負債が増加し、変更ごとに人々がさらに変更を恐れる悪循環に陥ります。
自己テストコードを使用すると、状況は異なります。ここでは、コードをクリーンアップするために小さな問題を修正することが安全に行えるという自信があります。なぜなら、間違いを犯した場合(あるいは「間違いを犯した場合」)、バグ検出器が作動し、迅速に回復して続行できるからです。そのセーフティネットにより、コードの状態を良好に保つ時間を費やすことができ、新しい機能の追加が着実に速くなるという好循環に陥ります。
このような利点は、テスト駆動開発(TDD)に関してよく話題にされますが、TDDと自己テストコードの概念を分離することが役立ちます。私はTDDを、自己テストコードを作成するという利点を持つ特定の実践と考えています。それは素晴らしい方法であり、TDDは私が大いに支持するテクニックです。しかし、コードを記述した後にテストを記述することによっても自己テストコードを作成できます。ただし、テスト(およびテストがパスする)が完了するまで、作業が完了したとは見なせません。自己テストコードの重要な点は、テストがあることであり、どのようにテストを得たかではありません。
自己テストコードを実践するチームの重要な行動の1つは、本番バグへの反応です。自己テストコードを使用するチームの通常の反応は、最初にバグを公開するテストを作成し、それから修正を試みることです。多くの場合、このテストの記述は、範囲を徐々に狭めて単体テストでバグが発生するまで到達する一連のテストになる可能性があります。これはデバッグテクニックとして有用であり、バグが修正されたら修正された状態を維持するためにも不可欠です。通常、チームは、このバグをきっかけに、同様の欠落しているテストを探します。姿勢としては、バグはコードの失敗だけでなく、テスト画面の失敗でもあると考えるべきです。
近年、本番環境での監視の重要性がますます高まっており、自己テストにも別の次元が見られるようになっています。継続的デリバリーにより、新しいバージョンのソフトウェアを迅速に本番環境に展開できます。このような状況では、チームは本番環境でバグを発見し、新しい修正版を展開するか、最後に正常に動作したバージョンにロールバックすることで迅速に修正することに多くの努力を注いでいます。
このエントリは、(はるかに小さい形式で)2005年5月5日に最初に公開されました。