不変テスト
2006年1月5日
契約によるデザイン(DbC)の支持者とテスト駆動開発(TDD)の支持者の間で、派手ではないものの長い論争があります。今はそれに関して詳しく踏み込みませんが、ダニエル・ジャクソンと話すときに思いついた、2つをまとめるアイデアを紹介します。
DbCでは、各クラスに対して不変性を定義します。この不変性は、常に真である必要があるクラスのプロパティを宣言します。オブジェクトは常に(何かの最中でない限り)不変性を満たす必要があります。Eiffelを使用して、クラス不変性はメソッドの呼び出し前(事前条件のチェック時)と後(事後条件のチェック時)に自動的にチェックされます。不変性における不具合が発生すると、例外がスローされます(パフォーマンス上の理由から、必要に応じてこのチェックを使用しなくすることもできます)。
このアイデアをTDDに適用すると、不変性をテストするための共通メソッドを、本番用クラスで定義し、テストコードでテストすることになります。
よくある些細な事例を紹介しましょう。
public class Bowler ... int overs, runs, wickets;
ボーラーの単純な不変性は、これらすべての値が非負であるべきというものです。したがって、次のように不変性を定義できます。
public boolean passesInvariant() { return (runs >= 0 && overs >= 0 && wickets >= 0); }
テスト中に初期化とテストの実行のフェーズの後、使ってください。
public void testConcedingRunsAddsToRunsScore() { Bowler botham = new Bowler(); // setup - showing my age assert botham.passesInvariant(); botham.concedeRuns(4); //exercise assert botham.passesInvariant(); assertEquals(4, botham.getRuns()); //verify }
私は自分で試したことはありませんし、それをやった人がいるということも知りません。しかし、興味深い考えとして皆さんにお伝えすることにしました。