パソコン練習日記

やってみたことを記録しています。Bloggerからこちらに引っ越して来ました。一部、画像がリンク切れしていますがひとつひとつ直すのは心が折れたのでそのままにします。

Visual Studioとコンテナを使ったCICDお勉強の記録3 単体テストの前後処理追加

ここの続き

このままテストを繰り返すとデータが溜まっていってテスト整合性保てなくなる場合があることや、テスト用のDBはコンテナで使い捨てにすることを踏まえ、前処理後処理をいれる。

前処理はこんな感じにしておく。DBが存在したら、どういう使われ方したかわからんからDropしてからDBを作成。そのあと、テスト用のテーブル作成。

[TestInitialize]
public void Setup()
{
    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();

        // データベースが存在するか確認し、存在する場合は削除
        string checkDbExistenceQuery = $"SELECT database_id FROM sys.databases WHERE Name = '{testDatabase}'";
        using (var command = new SqlCommand(checkDbExistenceQuery, connection))
        {
            var databaseId = command.ExecuteScalar();
            if (databaseId != null)
            {
                string dropDbQuery = $"DROP DATABASE {testDatabase}";
                using (var dropCommand = new SqlCommand(dropDbQuery, connection))
                {
                    dropCommand.ExecuteNonQuery();
                }
            }
        }

        // テスト用データベースの作成
        string createDbQuery = $"CREATE DATABASE {testDatabase}";
        using (var command = new SqlCommand(createDbQuery, connection))
        {
            command.ExecuteNonQuery();
        }

        // テスト用テーブルの作成
        string useDbQuery = $"USE {testDatabase}";
        string createTableQuery = "CREATE TABLE TestTable (date DATETIME NOT NULL, num INT NOT NULL)";
        using (var command = new SqlCommand($"{useDbQuery}; {createTableQuery}", connection))
        {
            command.ExecuteNonQuery();
        }
    }
}

後処理でも、使ったDBを削除するお片付け処理を入れとく

[TestCleanup]
        public void Cleanup()
        {
            using (var connection = new SqlConnection(connectionString))
            {
                connection.Open();

                // テスト用データベースの削除
                string dropDbQuery = $"DROP DATABASE {testDatabase}";
                using (var command = new SqlCommand(dropDbQuery, connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }

いちおう、動作確認。ブレークポイント置いてテストデバッグ

DB消えた

DB作成された

テーブル作成された。

もちろん、データなし。

テストも正常に終了

ということでもう一回テスト実行したら、前処理でDBがDropできなくてエラー。なんかがDB使っているからDropできんよ。とのこと
TestCleanup method DatabaseOperationTests.DataInserterTests.Cleanup threw exception. System.Data.SqlClient.SqlException: Cannot drop database "TestDB" because it is currently in use..

前処理と後処理それぞれのDrop処理の前にコネクション強制切断処理を追加
// データベースへのすべての接続を切断
        string alterDbQuery = $"ALTER DATABASE {testDatabase} SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
        using (var alterCommand = new SqlCommand(alterDbQuery, connection))
        {
            alterCommand.ExecuteNonQuery();
        }

これでとりあえず、テストを何回繰り返してもエラーにならなくなった

 

今時点で、最終的なテストプログラムは以下

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Data.SqlClient;
using SqlServerOperation;

namespace DatabaseOperationTests
{
    [TestClass]
    public class DataInserterTests
    {
        private readonly string server = "192.168.10.13";
        private readonly string username = "sa";
        private readonly string password = "P@$$w0rd";
        private readonly string testDatabase = "TestDB";
        private readonly string connectionString;

        public DataInserterTests()
        {
            connectionString = $"Server={server};Database=master;User Id={username};Password={password};";
        }

        [TestInitialize]
        public void Setup()
        {
            using (var connection = new SqlConnection(connectionString))
            {
                connection.Open();

                

                // データベースが存在するか確認し、存在する場合は削除
                string checkDbExistenceQuery = $"SELECT database_id FROM sys.databases WHERE Name = '{testDatabase}'";
                using (var command = new SqlCommand(checkDbExistenceQuery, connection))
                {
                    var databaseId = command.ExecuteScalar();
                    if (databaseId != null)
                    {
                        // データベースへのすべての接続を切断
                        string alterDbQuery = $"ALTER DATABASE {testDatabase} SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
                        using (var alterCommand = new SqlCommand(alterDbQuery, connection))
                        {
                            alterCommand.ExecuteNonQuery();
                        }

                        string dropDbQuery = $"DROP DATABASE {testDatabase}";
                        using (var dropCommand = new SqlCommand(dropDbQuery, connection))
                        {
                            dropCommand.ExecuteNonQuery();
                        }
                    }
                }

                // テスト用データベースの作成
                string createDbQuery = $"CREATE DATABASE {testDatabase}";
                using (var command = new SqlCommand(createDbQuery, connection))
                {
                    command.ExecuteNonQuery();
                }

                // テスト用テーブルの作成
                string useDbQuery = $"USE {testDatabase}";
                string createTableQuery = "CREATE TABLE TestTable (date DATETIME NOT NULL, num INT NOT NULL)";
                using (var command = new SqlCommand($"{useDbQuery}; {createTableQuery}", connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }

 

        [TestMethod]
        public void InsertData_InsertsCorrectly()
        {
            // Arrange
            var testConnectionString = $"Server={server};Database={testDatabase};User Id={username};Password={password};";
            var dataInserter = new DataInserter(server, testDatabase, username, password);
            var testDate = new DateTime(2021, 1, 1);
            int testNum = 1;

            // Act
            dataInserter.InsertData(testDate, testNum);

            // Assert
            using (var connection = new SqlConnection(testConnectionString))
            {
                connection.Open();
                string selectQuery = "SELECT date, num FROM TestTable WHERE num = @Value2";
                using (var command = new SqlCommand(selectQuery, connection))
                {
                    command.Parameters.AddWithValue("@Value2", testNum);
                    using (var reader = command.ExecuteReader())
                    {
                        Assert.IsTrue(reader.Read()); // レコードが存在することを確認
                        Assert.AreEqual(testDate, reader.GetDateTime(0)); // 日付が一致することを確認
                        Assert.AreEqual(testNum, reader.GetInt32(1)); // num が一致することを確認
                    }
                }
            }
        }

        [TestCleanup]
        public void Cleanup()
        {
            using (var connection = new SqlConnection(connectionString))
            {
                connection.Open();

                // データベースへのすべての接続を切断
                string alterDbQuery = $"ALTER DATABASE {testDatabase} SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
                using (var alterCommand = new SqlCommand(alterDbQuery, connection))
                {
                    alterCommand.ExecuteNonQuery();
                }

                // テスト用データベースの削除
                string dropDbQuery = $"DROP DATABASE {testDatabase}";
                using (var command = new SqlCommand(dropDbQuery, connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }

    }
}