パソコン練習日記

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

Visual Studioとコンテナを使ったCICDお勉強の記録4

ここの続き

テスト結果の値を標準出力させる

VSCodeとかEclipseとかだとどういう感じなのか知らないが、VisualStudioのテストエクスプローラだとこんな表示。結果がどういう値だったのか見たいけど出てこないので、見れない。

なので、出るようにしてみる。

MSTestでは、TestContext.WriteLine メソッドを使用してテスト中にカスタムメッセージを出力する。とのこと。

まずは、TestContext プロパティをテストクラスに追加

public TestContext TestContext { get; set; }

値をログに出力する処理を追加

TestContext.WriteLine("Expected date: {0}, Actual date: {1}", testDate, actualDate);
TestContext.WriteLine("Expected num: {0}, Actual num: {1}", testNum, actualNum);

なんかCS8618の警告が出る。クラスがnull非許容プロパティを持っているにもかかわらず、コンストラクター内でそのプロパティが明示的に初期化されていない場合に発生するとのこと。

GPTに聞いたら、こうやったらいいよ。と以下のアドバイスと説明もらった。

TestContext プロパティに default! を代入しています。default! は、null許容警告を無視するためのもので、プロパティがテスト実行時にMSTestフレームワークによって適切に初期化されることを前提としています。! はnull許容コンテキストでnull非許容型のデフォルト値を強制するために使用されます。

でも、クラス内に他にも初期化されていない非nullプロパティがある場合は、同様の方法で初期化を行う必要があったりするからちゃんと全体を見てね。とのこと。ふむ、全然わからん。

public TestContext TestContext { get; set; } = default!; // デフォルト値を設定

また、TestContext.WriteLine の呼び出しを reader.Read() が成功した後の if ブロック内に移動させたほうが、using ブロックの適切なスコープ内で行うようになるからAssert処理もちょっと変えたほうが良いよ。とのことで変更。

 

今回、最終的なテストコードは以下な感じに

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

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 TestContext TestContext { get; set; }= default!; // デフォルト値を設定

        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())
                    {
                        bool isRead = reader.Read();
                        Assert.IsTrue(isRead); // レコードが存在することを確認

                        if (isRead) // 読み取りが成功した場合のみログを出力
                        {
                            DateTime actualDate = reader.GetDateTime(0);
                            int actualNum = reader.GetInt32(1);

                            Assert.AreEqual(testDate, actualDate); // 日付が一致することを確認
                            Assert.AreEqual(testNum, actualNum); // num が一致することを確認

                            // 値がどうだったかをログに出力
                            TestContext.WriteLine("Expected date: {0}, Actual date: {1}", testDate, actualDate);
                            TestContext.WriteLine("Expected num: {0}, Actual num: {1}", testNum, actualNum);
                        }
                    }
                }
            }
        }

        [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();
                }
            }
        }
    }
}

これで、テスト時の値が見えるように