【Squishノウハウ】テストケース間の依存性を解消する方法

この記事はFinding & Fixing Dependencies Between Test Casesの抄訳です。

 

よし、うまく動いた!

突然ですが、業務中にこのセリフが自分自身の口から発されることはよくありますか?あるいは、同僚の口からはどうでしょうか?

あるシステムで動作するテストが、別のシステムで失敗することがあります。テスト対象のアプリケーション(AUT)は、実行されるオペレーティングシステムに依存します。テストケースのコードは、テストされるアプリケーションがビルドされたバージョンなどに依存します。あるいは、テストケースは互いに依存し合い、その実行順序は時に重要となります。

テストスイートが大きくなるにつれて、テストケース間に暗黙の依存関係ができてしまうことがあるのです。この記事では、テストケース間の依存関係がどこから来るのか、なぜダメなのか、そしてSquishを使ってそれを検出する方法についてご紹介します。

テストケース間の暗黙の依存関係の原因

テストケース間の依存関係は、意図的に導入されている可能性があります。

たとえば、複数のテストケースが実行中のアプリケーションにアタッチしたりデタッチしたりする場合(attachToApplication(英語)スクリプトコールを使用)や、テストケースごとにアプリケーションの状態をリセットしないほうがテストの実行速度を向上させることができる場合などです。

他には、後続のテストケースのシーケンスでアプリケーションの状態を再利用することにすることもできます。そうすれば、後続のテストケースは「ゼロから」始める必要はなく、むしろいくつかの追加ステップを実行するだけで済ませることができます。

しかし、2つ以上のテストケースの間の依存関係は、意図せずにできてしまうこともあります。あるテストケースがテストデータファイルを作成し、クリーンアップを怠ったためにそれを残してしまったとします。次のテストケースは、そのテストデータファイルを暗黙に再利用してしまうかもしれません。

テストケースが順番に実行されている限り、この依存関係があるにも関わらず、すべてがうまくいっているように見えるため、この問題が長い間気づかれないままであることがあります。

テストケースの依存性はなぜ問題なのか?

テストケース間の依存関係は、以下のような理由で問題となります。

  • テストケースが失敗した場合、問題の再現とデバッグの一環として、失敗したテストケースだけを単独で実行することができません。その代わりに、(多くの場合、未知の)先行するテストケースを同様に実行する必要があります。そのため、問題の原因究明が大幅に遅れてしまうことがあります。
  • 複数のテストケースでテストコードを再利用することは、より困難です。テストケースが、別のテストケースが以前に実行されたことを暗黙のうちに仮定している場合、この仮定はスクリプトコード内のどこにも表現されません。その結果、テストコードの一部を共有関数にファクタリングしても、そのコードは再利用できないかもしれません。なぜなら、そのコードは、別のテストケースの他のコードが先に実行されることを前提としているからです。この仮定は、他のテストケースからコードを呼び出すときに満たされないことがあります。
  • テストコードのリファクタリング時にエラーが発生しやすくなります。他のテストケースがあるテストケースの動作に依存している場合があるので、リファクタリングすると突然他のテストケースが失敗することがあります。テストスクリプトのコードを読んだだけでは、リファクタリングが機能的に影響を与えないことが想定されていたため、デバッグが困難となるのです。

したがって、テストケース間の暗黙の前提や相互作用を特定し、排除することが望まれるのです。

テストケースの依存関係を特定する方法

テストケース 'A' がテストケース 'B' の実行に先行する必要があるケースを特定するための非常にシンプルで効果的な方法は、まず 'B' を実行し、次に 'A' を実行するという逆の方法を試してみることです。この考え方を複数のテストケースからなるテストスイートに当てはめると、テストケースをシャッフルし、異なる順序で実行することになります。テスト実行のたびに異なる順序で実行することで、テストケース間の相互作用を特定し、排除できる可能性が高くなります。

しかし、一度依存関係が見つかったら、問題のある順序でテストケースを再実行できることが重要です。したがって、順序は完全にランダムではなく、決定論的であり、自由に再現可能であるべきなのです。

Squishでテストケースの実行順序をランダムにする

Squishでは、squishrunner(英語)コマンドラインツールを起動する際に--random引数を指定することで、テストスイートのテストケースをランダムな順序で実行することができます。コマンドラインのドキュメントには、以下のような説明があります:

--randomオプションは、テストケースをランダムな順序で実行するためのオプションです。使用されたシーケンス番号は、ログメッセージとしてレポートに出力されます。特定の順序を再現する必要がある場合は、--random オプションのパラメータとしてシーケンス番号を指定することができます。これは、ランダムなテスト実行中に発生した失敗を再現するために使用できます。シーケンス番号0は、新しいシーケンス番号が生成されることを示します。オプションの値が省略されたときと同じ動作になります。

 

以下に、実際にどのように動作するのかをご紹介します。

5つのテストケースを含むサンプルテストスイートをコマンドラインで実行する場合、以下のように実行します。

squishrunner --testsuite suite_examplesuite --reportgen html,/tmp/firstrun

結果として、テストケースが一定の順序で実行されたことを示すHTMLレポートを得ることができます:

次のように--random引数を使ってコマンドラインを拡張する場合は、以下のようになります:

squishrunner --testsuite suite_examplesuite --reportgen html,/tmp/secondrun --random

先ほどとは少し異なるレポートが作成されます:

テストケースが異なる順序で実行され、特定の乱数に対する一意の識別子を示す追加のログメッセージが出力されることが確認できます。この乱数を--randomスイッチに渡すことで、順番を再現することができます:

squishrunner --testsuite suite_examplesuite --reportgen html,/tmp/thirdrun --random 484681510

このように、テストケースは先ほどと同じ順番で実行されます:

おわりに

以上が、記事の内容となります。

SquishをはじめとするQtのQA(品質保証)ツールにご興味がおありの方は、Qt JapanのEメールアドレスjapan@qt.ioまでお気軽にご連絡ください。

概要のご説明から詳細な技術的相談、また無償のツールトライアルのご案内も行っております。


Blog Topics:

Comments