基本的に、あなたが話しているのは統合テストです。これらはユニットテストとは異なります。統合テストの例としては、自動UIテストやコード化UIテストがあります。私が取り組んだほとんどのプロジェクトでは、両方のタイプのテストを実施しました。プロジェクトにも両方のタイプを含めることを強くお勧めします。
これら両方のテストの背後にある哲学はわずかに異なります。
- ユニットテストは、機能の分離されたビットをテストすることを目的としています。
- それらは非常に高速であることが意図されています。
- 開発者は、妥当な時間内にそれらすべてを自分のマシンで実行できる必要があります。
この哲学にはさまざまな結果があります。
- 単体テストは分離された機能をテストしているため、モックとスタブを使用して残りの環境を分離し、ごく一部の機能のみに焦点を当てる必要があります。
- 分離は、これらのテストを作成する際の「デザイン思考」に役立ちます。実際、開発者は設計および再設計プロセスの一環としてコードと単体テストを積極的かつ継続的に変更しているため、これが単体テストを高速にする必要がある理由です。単体テストをセットアップ、変更、および実行するためのオーバーヘッドは非常に低いはずです。解決しようとしている問題以外のすべてを無視して、設計とテストをすばやく繰り返して繰り返すことができるはずです。これは、TDDの背後にある考え方であり、テスト可能な優れたコードの記述に役立つという主張です。過度に複雑な単体テストの設定に長い時間を費やしている場合は、設計の再検討を開始する必要があります。
- 高速な性質は、継続的インテグレーションビルドの一部としてこれらを実行できることを意味します。
- 欠点は、各機能を個別にテストしているため、それらがすべて全体として連携して機能するかどうかわからないことです。モックを作成するたびに、システムの残りの部分がどのように機能し、システムの残りの部分が現在意図されたとおりに機能している(つまり、展開または実行の一部として他に何も壊れていない)という仮定を暗黙のうちに焼き付けています。またはOSのパッチなど)
統合テストは、機能をエンドツーエンドでテストすることを目的としています。システムのいかなる部分もモックアウトまたは分離しないようにしてください。
この哲学にはまたさまざまな結果があります。統合テストを高速にする必要はないことに注意してください。
- 統合テストは、その性質上、完全なデプロイメントの後に実行する必要があります(コードがコンパイルされるとすぐに実行できる単体テストとは対照的です)。
- 時間がかかるため、CI環境の一部として実行することはありませんが、定期的に実行する必要があります。私たちは通常、ナイトリービルドの一部としてそれらを実行します。または、1日2回実行することもできます。
- 統合テストはシステム全体に対してブラックボックスアプローチを採用しているため、実際にシステムを構築する方法について「デザイン思考」を行うのに実際には役立ちません。しかし、それはシステム全体の仕様について考えるのに役立ちます。つまり、システムが何かを行う方法ではなく、システムが行うべきこと。
どちらの場合も、アトミックであるテストのルールが引き続き適用されることに注意してください。各テストは他のテストとは異なります。このようにして、テストが失敗したときに、テストが失敗する原因となっているすべての条件を確認し、それを修正することに集中できます。統合テストがシステムのできるだけ多くの部分に影響を与えるだけです。
現在のプロジェクトの例を示します。
新しいテーブルをDBに追加し、それをすべてのレイヤーに通してUIに表示する必要がある、少しの機能を作成する必要があるとします。
まず、ビジネスロジッククラス、ドメインクラスの作成、適切なWebサービスの作成、ビューモデルの構築、データベースの変更などを行います。これらのそれぞれを実行しながら、現在作成しているコードをテストするためのユニットテストを作成します。したがって、ビジネスロジッククラスを構築するときは、クラス内のロジックが有効であることを確認するために他のすべてをモックアウトします(たとえば、60歳以上のクライアントは自動車保険の50%割引を受けるなど)。
これを行ったら、展開スクリプト/パッケージなどを更新して展開できるようにする必要があります。つまり、データベース作成SQLスクリプトやデータベース変更SQLスクリプトなどを更新します(この場合、これは複雑なプロセスになります)。
次に、統合テストを作成します。この場合、SQLServerからWebサービスにテストする可能性があります。各テストのセットアップおよびティアダウンメソッドを含むSQL統合テスト基本クラスがあります。セットアップでは、SQLデプロイメントスクリプトを使用して新しいデータベースを作成します。各テストは、テストデータのSQLスクリプトも指定します。したがって、たとえば、このテストデータスクリプトは、年齢が70歳のクライアントテーブルに新しいレコードを挿入する場合があります。このスクリプトは、テストの「アレンジ」の一部として実行します。次に、Webサービス呼び出しを行って60より古いクライアントを検索します。これはテストの「Act」部分であり、結果から、DBに挿入したユーザーのみが返されることを確認します。テストの最後に、データベースが削除されます。SQLデータベースの列がない場合、ここでバグを検出しました。
一部の機能では、Oracleデータベースと対話する必要があります。たとえば、新しいレコードがOracleに追加された場合、trigger / dbプロシージャが開始され、そのレコードがSQLに転送されてから、レイヤーを起動する必要があります。この場合、OracleSQL統合テストの基本クラスがあります。ご想像のとおり、これは同様のパターンに従いますが、OracleとSQLの両方を作成します。dbsはテストデータをOracleに挿入し、テストの最後に両方を吹き飛ばします。
開発者は通常、統合テストを作成するためにWebサービスレイヤーを選択します。一方、テスターはUI自動化ツールを使用して、データが実際に画面に表示されていることを確認します。たとえば、Webページに移動し、検索ボタンをクリックし、年齢ボックスに「60」を入力し、検索ボタンをクリックするなどのテストを記録します。このテストでは、開発者が作成したテストデータを挿入するのと同じテストデータsqlスクリプトを利用する場合があります。 (または、テストチームが開発者のところに来て、考えられる非常に複雑なデータを挿入するためのsqlスクリプトの作成を支援するように依頼する場合があります)。ただし、重要なのは、テストデータ挿入スクリプトが作成されると、同じ基盤システムを利用してデータベース全体を吹き飛ばし、新しいデータベースを作成し、テストデータを挿入して、指定されたテストを実行することです。
したがって、質問に答えるには、単体テストと統合テストの2種類のテストが必要になります。データベースを作成/削除するための基本クラスまたはヘルパーメソッドの作成、システムの他のコンポーネントのインストール/アンインストールのための展開の自動化などに、初期作業を行う必要がある場合があります。いずれにせよ、最終的な展開ではこれを行う必要があります。統合テストは、展開戦略にも密接に関連し、依存します。これは利点であり、私の意見では欠点ではありません。最初はすべてを設定するのは面倒かもしれませんが、統合テストが暗黙的にテストしていることの1つは、デプロイメントメカニズムです。システムに必要なコンポーネントの展開/インストールに問題がある場合は、できるだけ早くそれについて知りたいと思います。
優れた一連のテストは非常に貴重です。また、分離され、厳密で、包括的である必要があります。テストは、必要のないときに失敗するべきではありませんが、さらに重要なことに、必要なときに失敗する必要があります。そして、彼らが失敗したとき、あなたは彼らにできるだけ多くの情報を提供し、あなたに失敗の正確な場所を教えてもらいたいのです。これにより、問題の修正がはるかに簡単になります。このテストスイートの構築に取り掛かるときはいつでも、すぐにそれ自体の代償を払うだけではありません。