テスト戦略を定義すると、テスト・リソースをコードの適切な部分に適切な時点で集中させるのに役立ちます。
中規模から大規模のアプリケーションを作成するときに、最初に頭に浮かぶ質問は「どこから始めるか」で、その次は「次に何をするか」です。ガイダンスがメトリックの形式で用意されています。これは、メソッド、クラス、およびテスト対象コンポーネント (CUT: components-under-test) の複雑さと信頼性を分析して戦略を決定するのに役立ちます。
コンポーネント・テストでは、機能テストとは対照的に、個々のソフトウェア・コンポーネント (クラス、メソッド、Enterprise JavaBeans™ (EJB)、および Web サービス・コンポーネント) に焦点が当てられます。コンポーネント・テストのポイントは、コンポーネントが適切に機能することを個別に確認できるように、各コンポーネントを分離することです。必要な場合は、スタブを使用して他のコンポーネントを置き換えて、テスト結果がテスト対象コンポーネントの振る舞いに限定されるように条件付けできます。一度信頼できるテスト・スイートが作成されたら、それを定期的に再実行して、CUT で回帰が発生していないことを確認できます。
サブシステム・レベル・テスト (統合テストとも呼ばれます) の目的は、なんらかのサービスを提供するために連携する必要のある一連の統合されたクラスのテストです。多層環境では、サブシステムがそれらの層の 1 つである場合があります。サブシステム・レベル・テストでは、テスト対象コンポーネントとその他のサブシステムとの間のインターフェースを検査することに焦点を当てています。これらのテストでは、サブシステムの異なるオブジェクト間の相互作用を実際に行わせてみます。
確かにサブシステム・レベル・テストは実施するテスト全体の中で重大な役割を果たすものですが、サブシステム・レベル・テストを必ずメソッド・レベル・テストとクラス・レベル・テストで補足してください。 サブシステム・レベル・テストのみに焦点を当てていると、表面的なテスト範囲しかカバーされません。なぜなら、サブシステム・レベル・テストでは個別クラスを十分には制御できないからです。
メソッド・レベル・テストでは、メソッド・コード内に定義されているさまざまな条件を、他のすべてのメソッドから分離して実際に試してみます。通常は、考えられるすべての入力をメソッドが正しく処理するかどうかを確認することに焦点が置かれます。多くのケースでは、一連のメソッドを分離してテストすると、不完全なテスト範囲しかカバーできません。また、private メソッドなどの一部のメソッドは、分離してテストすることはできません。 (private メソッドは、オブジェクトの状態に大きな影響を与える可能性があり、他のメソッド呼び出しの振る舞いを変更する可能性があります。)
1 つのクラスのメソッド間での相互作用が問題の原因となるのはよくあることです。これらの問題を発見するのに最適な方法は、メソッドをさまざまなシナリオで実行してみることです。したがって、常にメソッド・レベル・テストをクラス・レベル・テストまたはサブシステム・レベル・テスト (あるいはその両方) と組み合わせる必要があります。ステートレス・クラスのテストのような一部のケースでは、メソッド・レベル・テストにのみ焦点を当てても構いません。また、その他のケースでは、メソッド・レベル・テストは回避して、クラス・レベル・テストにのみ焦点を当てることにする場合もあります。
メソッド・レベル・テストを成功させる鍵は、実際にテストすべきメソッドの判別です。以下の表に、メソッド・レベル・テストに関する、よくある質問の幾つかに対する回答を示します。
質問 | 回答 |
---|---|
メソッドがスーパークラスから継承されるものである場合はどうするか。 | メソッドがスーパークラスから継承されるもので、すでにスーパークラスのパーツとしてテスト済みである場合は、このメソッドに対して継承オブジェクトのコンテキストでのメソッド・レベル・テストを行う必要はありません。 ただし、継承オブジェクトのクラス・レベル・テストのコンテキストでは、このメソッドを使用する必要があります。 |
メソッドが親クラスのメソッドをオーバーライドする場合はどうするか。 | メソッドを親クラスのコンテキストでテスト済みであっても、そのオーバーライドするメソッドを再テストする必要があります。 |
メソッドが多重定義またはオーバーライドされる場合はどうするか。 | メソッドが多重定義されるのは、同じクラス内に名前が同じでパラメーターが異なるメソッドが複数存在する場合です。メソッドがオーバーライドされるのは、メソッドの宣言はあるクラスで行われて、メソッドの実装の定義または変更はサブクラスで行われる場合です。オーバーライドされるメソッドを使用すると、1 つのオブジェクト型にポリモアフィックな性質を持たせられます。どちらのケースでも必ず、これらのクラス・メソッドのそれぞれの実装を個別にテストしてください。 |
抽象テストを使用して、Java のインターフェース、抽象クラス、およびスーパークラスをテストできます。抽象クラスを単独で実行することは実際には不可能ですが、インターフェースを実装するクラス、抽象クラスを実現するクラス、またはスーパークラスから継承されるクラスに対して抽象テストを適用することはできます。
Enterprise JavaBean (EJB) に対するテストは、通常はその EJB のビジネス・ロジックの検査と、その EJB のライフ・サイクル・メソッドが正常終了するか失敗するかの検査から構成されます。これを行うには、Bean クラスに定義されているメソッドを、そのメソッドの各種のインターフェースを通じて呼び出すことでテストします。テストは、EJB と同じコンテナー内に置くことも、アプリケーション・サーバーの外側に置くこともできます。
EJB をテストするのに最適な方法は、EJB をアプリケーション・サーバーにデプロイして、そのコンテナーのコンテキストで実行することです。 EJB がローカル・インターフェースを持つ場合、その EJB は、(例えば別の EJB を使用して) 同じアプリケーション・サーバー内からテストする必要があります。 EJB がリモート・インターフェースを持つ場合、その EJB は、アプリケーション・サーバーの外側で実行されている Java クライアントを使用してテストできます (ただし、ネットワーク・トラフィックが増加するという欠点があります)。 どちらの方法でも、テスト対象 EJB の振る舞いを分離できるように、その EJB から呼び出されるコンポーネントをスタブする必要があります。
コンテナー管理パーシスタンスまたは Bean 管理パーシスタンス (CMP または BMP) のいずれかを持つステートフルおよびステートレス (どちらでも可) のセッション Bean とエンティティー Bean をテストできます。テストするためには、すべての Bean がリモート・インターフェースまたはローカル・インターフェースのどちらかを持っている必要があります。メッセージ駆動型 Bean のテストは、現在はサポートされていません。
EJB テストのプロセスを単純化できるテスト・パターンが幾つかあります。
Web サービスのような分散コンポーネントをテストする場合のアプローチは、基本的には他のすべてのコンポーネント・テストの場合と同じです。最適なアプローチは、サーバーに対して一連の要求を実行して、サーバーの応答が予期される戻り値と一致するかどうかを検査することです。
Web サービス記述文書 (WSDL) に記述されているように、Web サービス・インターフェースは Web サービス用のコンポーネント・テストを自動生成するのに必要な入力です。