
私たちのテスト スイートの一部として、すべてをモックし、データベース接続を必要としないユニット テストの他に、データベースを必要とする統合テストもあります。
統合テストが必要なのは、多くのレガシー コードを扱っており、高レベルのテストを実行できるためです。
セットアップ
データベースは SQL Server 2008 R2 で、OS と SQL Server の両方に対して最新の Windows 更新プログラムがすべて適用された Windows Server 2008 R2 システム上で実行されます。
データベースサーバーを実行するVMは、私たちのビルドインフラストラクチャの一部であり、もちろんイメージに基づいて毎朝6時に新しく作成され、午後10時に破棄されます。したがって、SQL Serverエージェントとサービスは基本的に新しい毎日開始されます。最初のビルドは午前 7 時に実行されるため、マシンにはすべてのサービスを開始して読み込むのに十分な時間があります。
データベース サーバーは無制限の数の接続を許可するように構成されており、名前付きパイプと TCP 接続が有効になっています。
データベースへの接続は、さユーザー。
生産データベースの縮小スナップショットがあります。.mdf ファイルには、テストを実行するために必要なすべてのテーブル、ビュー、ストアド プロシージャ、および最小限のデータ セットが含まれています。
統合テストを実行すると、テストセットアップは.mdf ファイルSQL ServerインストールのDATAフォルダにb.mdf. b.mdf は次のコマンドを使用してデータベースにアタッチされます。
CREATE DATABASE Foo ON (FILENAME = N'Path\To\b.mdf') FOR ATTACH
テストが実行され、データベース操作が実行され、テスト フィクスチャのテスト ティアダウンでデータベースが切り離され、b.mdf ファイルが削除されます。
デタッチを実行するには、次の 2 つのコマンドを個別に実行します。
ALTER DATABASE Foo SET SINGLE_USER WITH ROLLBACK IMMEDIATE
EXEC master.dbo.sp_detach_db @dbname = N'Foo'
したがって、実際には、次のレイアウトのテスト フィクスチャ セットがあります。
Setup();
Test_1();
Test_2();
Test_3();
TearDown();
各セットアップでは、新しいデータベースが作成され、すべてのテストが実行され、データベースが削除されるため、次のテキスト フィクスチャはクリーンな新しいデータベースで開始されます。
合計で約 50 個のテキスト フィクスチャがあり、それぞれに 10 個のテストが含まれています。つまり、データベースの接続と切断が 50 回行われ、約 500 個のテストが実行されます。
問題
ここ数週間、統合テストに関連する失敗したビルドの数が増えているのがわかります。セットアップ全体がローカル マシンでも他の開発者のマシンでも完璧に動作しているので、テストは正常だとわかっています。問題を報告しているのはビルド サーバーだけです。
SetUp Error : Namespace.Class.Method
SetUp : System.Data.SqlClient.SqlException : Cannot open database "Foo" requested by the login. The login failed.
Login failed for user 'sa'.
もちろん、グーグルで調べたところ、ログインは正しいことが分かりました。失敗するテストが常に同じとは限らないので、それが分かります。テストスイート全体を10回実行すると、10回中8回は失敗しますが、失敗を報告するテストは毎回異なります。エラーメッセージは同じで、ログインできないと表示され、時には次のようにも報告されます。パイプの反対側にはプロセスがない。
また、名前付きパイプと TCP 接続が有効になっていることを確認し、許可された接続の数を確認しました。... ERRORLOG ファイルも確認しましたが、データベースに直接関連するものは何も含まれていませんでした。
私の推測では、何らかの奇妙な理由で、それが速すぎたり遅すぎたりして、データベースを適切に接続または切断できないか、呼び出しがSINGLE_USER
問題を引き起こしているのではないかと思います。私が収集した情報によると、ログインが原因で 1 つのテストが失敗した場合、b.mdf ファイルは使用中のため削除できません。
そこで質問なのですが、他に試せることは何かありますか?より詳しい情報を提供してくれるエラー ログ ファイルや特定のメッセージはありますか?アタッチとデタッチが成功したかどうかを確認するためにできることはありますか?(デタッチの失敗がログインの問題を引き起こす可能性はありますか?)デタッチ操作は非同期なので、次の呼び出しが行われたときにまだ完了していない可能性はありますか?
答え1
最初の問題: ログイン失敗エラー。
テストの実行時にデータベースがまだ完全に初期化されていない可能性が高くなります。
手順でこれを検出する必要があります。これを行う簡単な方法は、マスター データベースを照会して、ターゲット データベースが稼働しているかどうかを確認することです。
IF (select name from sys.databases
where name = 'foo' and state_desc = 'ONLINE' and is_in_standby = '0') IS NOT NULL
PRINT 'database not found';
2 番目の問題: パイプのもう一方の端にプロセスがありません。
TCP/IP 経由で接続していない場合、この背後にあるエラーはしばしば不明瞭になります。
直接 IP 接続を有効にしてみるか、他のエラーに注目してください。おそらく、他のエラーがこの問題の原因です。