テストとデータベース。 テストによって行われた変更をロールバックする方法は?

タスクステートメント



単体テストがデータベースで動作し、それを変更する場合-実行の結果が再現可能になるように何をする必要がありますか?

答えは、テストの前にベースをきれいにすることです。 ただし、データベースに何らかの種類のデータセットを保持して、テストからデータが書き込まれないようにします(このようなデータを「基本セット」と呼びます)。 したがって、テスト自体を単純化し、何度も設定します。



決定のレビュー



これはどのように実装できますか? いくつかのオプションが思い浮かびます:



(他にどのようなオプションを提案しますか?)



決定の選択



「クリーニングスクリプト」に基づいた同様のソリューションでしばらく作業を行った後、何か新しいことを試してみることにしました。 この新しいオプションは「バックアップ」にありました。

私はスナップショットがより好きであることに注意しますが、それらはMS Sql Expressにはありません。

全体のアプローチは、.NetプラットフォームとMS Sqlサーバー用に開発されました。



実装



最初のテストでは、次の問題が明らかになりました。





それでは、実装の時間です。

テスト前に、データベースへの不要な接続を削除するためにSetUpスクリプトが実行され、その後バックアップから復元されることが判明しました。



ユーザー切断スクリプト:

DECLARE @twho TABLE( SPID int , ecid int , [STATUS] NVARCHAR(64) , [Loginame] NVARCHAR(64) , [HostName] NVARCHAR(64) , [Blk] int , [DBName] NVARCHAR(64) , cmd NVARCHAR(64), request_id INT) INSERT INTO @twho EXEC SP_WHO DECLARE spid_cursor CURSOR FOR SELECT SPID FROM @twho WHERE DBName = @dbname OPEN spid_cursor DECLARE @SpidToClose INT FETCH NEXT FROM spid_cursor INTO @SpidToClose WHILE @@FETCH_STATUS = 0 BEGIN IF @@SPID <> @SpidToClose BEGIN -- kill     . declare @str varchar(32) set @str='KILL ' + cast(@SpidToClose as varchar(16)) exec(@str) END FETCH NEXT FROM spid_cursor INTO @SpidToClose END CLOSE spid_cursor; DEALLOCATE spid_cursor;
      
      







データベースをロールバックするスクリプト:

 USE master RESTORE DATABASE [FSID_test] FROM DISK = N'c:\BackupPathHere\BackupNameHere.bak' WITH FILE = 2
      
      







SetUpテストから呼び出すコード

 public static void RevertDb() { //      -     .     var sb = new SqlConnectionStringBuilder(Utilities.ConnectionDb) { ConnectTimeout = 2, ApplicationName = "FSID Tests, clearing" }; using (var con = new SqlConnection(sb.ToString())) { con.Open(); using (var cmd = con.CreateCommand()) { cmd.CommandText = Utilities.CommandKillAllConectionsToDb; cmd.Parameters.AddWithValue("@ dbname", sb.InitialCatalog); //       var result = cmd.ExecuteScalar(); } } //      -     , .     .  . SqlConnection.ClearAllPools(); using (var con = new SqlConnection(sb.ToString())) { con.Open(); using (var cmd = con.CreateCommand()) { cmd.CommandText = Utilities.CommandRevertTestDb; cmd.ExecuteScalar(); } } }
      
      







今ではすべてが非常に単純に見えますが、その過程で、以前に遭遇したいくつかの小さな問題を解決する必要がありました。





したがって、これらすべてを実際に試した結果、このアプローチは実行可能で便利であると安全に言えます。 機能:





UPD:

コメントには2つのことが提案されています。



私が提案したアプローチのようなこれらのアプローチには欠点がないわけではありません(作成されたデータベースを削除する必要があり、トランザクションは常に高速にロールバックされず、ストアドプロシージャに制限を課します)が、真剣に検討する価値があります。



All Articles