Visual Studio を使用して .NET クラス ライブラリをテストする

重要

Microsoft は、Visual Studio for Mac の提供終了を発表しました。 Visual Studio for Mac は、2024 年 8 月 31 日でサポートが終了します。 代替手段は次のとおりです。

  • C# Dev Kit および関連する拡張機能 (.NET MAUIUnity など) を含む Visual Studio Code。
  • Mac 上の VM で Windows 上で実行されている Visual Studio。
  • クラウド内の VM の Windows 上で実行されている Visual Studio。

詳細については、「Visual Studio for Mac 提供終了のお知らせ」を参照してください。

このチュートリアルでは、テスト プロジェクトをソリューションに追加して、単体テストを自動化する方法について説明します。

必須コンポーネント

単体テスト プロジェクトを作成する

単体テストでは、開発および公開時に自動化されたソフトウェア テストが提供されます。 MSTest は、選択できる 3 つのテスト フレームワークのうちの 1 つです。 これ以外は、xUnitnUnit です。

  1. Visual Studio for Mac を起動します。

  2. Visual Studio for Mac を使用して .NET クラス ライブラリを作成する」で作成した ClassLibraryProjects ソリューションを開きます。

  3. [ソリューション] パッドで、ctrl キーを押しながら ClassLibraryProjects ソリューションをクリックし、 [追加]>[新しいプロジェクト] の順に選択します。

  4. [新しいプロジェクト] ダイアログで、 [Web and Console]\(Web とコンソール\) ノードから [テスト] を選択します。 [MSTest プロジェクト] を選択してから [次へ] を選択します。

    Visual Studio Mac New Project dialog creating test project

  5. [ターゲット フレームワーク] として [.NET 5.0] を選択し、 [次へ] を選択します。

  6. 新しいプロジェクトに "StringLibraryTest" という名前を付けて、 [作成] を選択します。

    Visual Studio Mac New Project dialog providing project name

    Visual Studio によって、次のコードを含むクラス ファイルが作成されます。

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
            }
        }
    }
    

    単体テストのテンプレートで作成されたソース コードにより、次の処理が行われます。

    [TestClass]でタグ付けされたテスト クラスの [TestMethod] でタグ付けされた各テスト メソッドが、単体テスト実行時に自動実行されます。

プロジェクト参照を追加する

テスト プロジェクトが StringLibrary クラスと連動するように、StringLibrary プロジェクトへの参照を追加します。

  1. [ソリューション] パッドで、StringLibraryTest の下にある [依存関係]ctrl キーを押しながらクリックします。 コンテキスト メニューから [参照の追加] を選択します。

  2. [参照] ダイアログで、 [StringLibrary] プロジェクトを選択します。 [OK] を選択します。

    Visual Studio Mac Edit References dialog

単体テスト メソッドの追加と実行

Visual Studio で単体テストを実行すると、TestClassAttribute 属性でマークされたクラス内で、TestMethodAttribute 属性でマークされた各メソッドが実行されます。 テスト メソッドは、最初の失敗が検出されたとき、またはそのメソッドに含まれているすべてのテストが成功したときに終了します。

一般的なテストでは、Assert クラスのメンバーが呼び出されます。 多くのアサート メソッドは最低 2 つのパラメーターを含んでいます。1 つは予期されるテスト結果、もう 1 つは実際のテスト結果です。 次の表に、Assert クラスの頻繁に呼び出されるメソッドをいくつか示します。

Assert メソッド 関数
Assert.AreEqual 2 つの値または 2 つのオブジェクトが等しいことを確認します。 値またはオブジェクトが等しくない場合、アサートは失敗します。
Assert.AreSame 2 つのオブジェクト変数が同じオブジェクトを参照していることを確認します。 変数が別々のオブジェクトを参照している場合、アサートは失敗します。
Assert.IsFalse 条件が false であることを確認します。 条件が true の場合、アサートは失敗します。
Assert.IsNotNull オブジェクトが null でないことを確認します。 オブジェクトが null である場合、アサートは失敗します。

また、テスト メソッドで Assert.ThrowsException メソッドを使用して、スローすることが期待される例外の種類を示すこともできます。 指定した例外がスローされない場合、テストは失敗します。

StringLibrary.StartsWithUpper メソッドのテストでは、大文字で始まる文字列を多く用意します。 これらの場合ではメソッドが true を返すと予測されるので、Assert.IsTrue メソッドを呼び出すことができます。 同様に、大文字以外で始まる文字列を多く用意します。 これらの場合ではメソッドが false を返すと予測されるので、Assert.IsFalse メソッドを呼び出すことができます。

ライブラリ メソッドは文字列を処理するため、空の文字列 (String.Empty) (文字がなく Length が 0 である有効な文字列)、および初期化されていない null 文字列を正しく処理することも確認します。 しかし、StartsWithUpper を静的メソッドとして直接呼び出して、単一の String 引数を渡すこともできます。 または、null に割り当てられた string 変数の拡張メソッドとして StartsWithUpper を呼び出すこともできます。

メソッドを 3 つ定義します。これらのメソッドでは、文字列配列の各要素に対して Assert メソッドが呼び出されます。 メソッドのオーバーロードを呼び出します。これにより、テストが失敗した場合に表示されるエラー メッセージを指定できます。 このメッセージによって、エラーの原因となった文字列が識別されます。

テスト メソッドを作成するには

  1. UnitTest1.cs ファイルを開き、コードを次のコードに置き換えます。

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestStartsWithUpper()
            {
                // Tests that we expect to return true.
                string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsTrue(result,
                           string.Format("Expected for '{0}': true; Actual: {1}",
                                         word, result));
                }
            }
    
            [TestMethod]
            public void TestDoesNotStartWithUpper()
            {
                // Tests that we expect to return false.
                string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " " };
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsFalse(result,
                           string.Format("Expected for '{0}': false; Actual: {1}",
                                         word, result));
                }
            }
    
            [TestMethod]
            public void DirectCallWithNullOrEmpty()
            {
                // Tests that we expect to return false.
                string?[] words = { string.Empty, null };
                foreach (var word in words)
                {
                    bool result = StringLibrary.StartsWithUpper(word);
                    Assert.IsFalse(result,
                           string.Format("Expected for '{0}': false; Actual: {1}",
                                         word == null ? "<null>" : word, result));
                }
            }
        }
    }
    

    TestStartsWithUpper メソッドの大文字のテストには、ギリシャ語の大文字のアルファ (U+0391) とキリル文字の大文字 EM (U+041C) が含まれています。 TestDoesNotStartWithUpper メソッドの小文字のテストには、ギリシャ語の小文字のアルファ (U+03B1) とキリル文字の小文字 Ghe (U+0433) が含まれています。

  2. メニュー バーから、 [ファイル]>[名前を付けて保存] の順に選択します。 ダイアログで、 [エンコード][Unicode (UTF-8)] に設定されていることを確認します。

    Visual Studio Save File As dialog

  3. 既存のファイルを置き換えるかどうかを確認するメッセージが表示されたら、 [置換] を選択します。

    UTF8 でエンコードされたファイルにソース コードを保存できなかった場合、ASCII ファイルとして保存される場合があります。 その場合は、ランタイムで ASCII 範囲外の UTF8 文字が正確にデコードされず、テスト結果が正確でなくなります。

  4. 画面の右側の [単体テスト] パネルを開きます。 メニューから [表示]>[テスト] を選択します。

  5. [ドッキング] アイコンをクリックして、パネルを開いたままにします。

    Visual Studio for Mac Unit Tests panel dock icon

  6. [すべて実行] ボタンをクリックします。

    すべてのテストに成功します。

    Visual Studio for Mac expected test passes

テストの失敗の処理

テスト駆動開発 (TDD) を行っている場合、最初にテストを作成すると、1 回目のテスト実行は失敗します。 その後、テストを成功させるコードをアプリに追加します。 このチュートリアルでは、検証するアプリ コードを記述した後にテストを作成したため、テストが失敗することはありませんでした。 テストの失敗が予想されるときにテストが失敗することを検証するには、テスト入力に無効な値を追加します。

  1. TestDoesNotStartWithUpper メソッドの words 配列を変更し、文字列 "Error" を含めます。 ソリューションをビルドし、テストを実行するときに、Visual Studio では、自動的に開いているファイルが保存されるため、ファイルは保存する必要はありません。

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
  2. テストをもう一度実行します。

    今回は、 [テスト エクスプローラー] ウィンドウに、2 つのテストが成功し、1 つが失敗したことが示されます。

    Test Explorer window with failing tests

  3. ctrl キーを押しながら、失敗したテスト、TestDoesNotStartWithUpper の順にクリックして、コンテキスト メニューから [結果パッドを表示する] を選択します。

    [結果] パッドに、アサートによって生成されたメッセージが表示されます。"Assert.IsFalse failed. Expected for 'Error': false; actual:True" が表示されます。 エラーのため、配列内の "Error" の後ろの文字列はテストされませんでした。

    Test Explorer window showing the IsFalse assertion failure

  4. 手順 1 で追加した文字列 "Error" を削除します。 テストを再実行すると、テストは成功します。

ライブラリのリリース バージョンのテスト

これで、ライブラリのデバッグ ビルドを実行したときにすべてのテストが成功したので、さらにライブラリのリリース ビルドに対してテストを行います。 コンパイラの最適化などのさまざまな要因により、デバッグ ビルドとリリース ビルドとでは動作が異なる場合があります。

リリース ビルドをテストするには、次の操作を行います。

  1. Visual Studio のツールバーで、ビルド構成を [デバッグ] から [リリース] に変更します。

    Visual Studio toolbar with release build highlighted

  2. [ソリューション] パッドで、ctrl キーを押しながら StringLibrary プロジェクトをクリックし、コンテキスト メニューから [ビルド] を選択してライブラリを再コンパイルします。

    StringLibrary context menu with build command

  3. 単体テストをもう一度実行します。

    テストが成功します。

テストのデバッグ

IDE として Visual Studio for Mac を使用する場合は、「チュートリアル:Visual Studio for Mac を使用して .NET コンソール アプリケーションをデバッグする」に記載されているのと同じプロセスに従って、単体テスト プロジェクトを使用してコードをデバッグできます。 ShowCase アプリ プロジェクトを開始する代わりに、ctrl キーを押しながら StringLibraryTests プロジェクトをクリックし、コンテキスト メニューから [プロジェクトのデバッグを開始] を選択します。

Visual Studio により、デバッガーがアタッチされた状態でテスト プロジェクトが開始されます。 実行は、テスト プロジェクトまたは基になるライブラリ コードに追加したブレークポイントで停止します。

その他の技術情報

次の手順

このチュートリアルでは、クラス ライブラリの単体テストを行いました。 ライブラリをパッケージとして NuGet に発行した場合、他のユーザーもそれを使用できます。 方法については、次の NuGet のチュートリアルに従ってください。

ライブラリを NuGet パッケージとして発行した場合、他のユーザーもそれをインストールして使用できます。 方法については、次の NuGet のチュートリアルに従ってください。

ライブラリはパッケージとして配布する必要はありません。 それが使用されるコンソール アプリにバンドルすることができます。 コンソール アプリを発行する方法については、このシリーズの前のチュートリアルを参照してください。