チュートリアル: Visual Studio を使用して .NET で .NET クラス ライブラリをテストする
このチュートリアルでは、テスト プロジェクトをソリューションに追加して、単体テストを自動化する方法について説明します。
必須コンポーネント
- このチュートリアルでは、「Visual Studio を使用して .NET クラス ライブラリを作成する」で作成するソリューションを使用します。
単体テスト プロジェクトを作成する
単体テストでは、開発および公開時に自動化されたソフトウェア テストが提供されます。 MSTest は、選択できる 3 つのテスト フレームワークのうちの 1 つです。 その他は xUnit と nUnitです。
Visual Studio を起動します。
「Visual Studio を使用して .NET クラス ライブラリを作成する」で作成した
ClassLibraryProjects
ソリューションを開きます。「StringLibraryTest」 という名前の新しい単体テスト プロジェクトをソリューションに追加します。
ソリューション エクスプローラーでソリューションを右クリックし、[追加]>[新しいプロジェクト] の順に選択します。
[新しいプロジェクトの追加] ページで、検索ボックスに「mstest」と入力します。 言語の一覧から [C#] または [Visual Basic] を選択し、次に、プラットフォームの一覧から [すべてのプラットフォーム] を選択します。
MSTest テスト プロジェクト テンプレートを選択し、[次へ] を選択します。
[新しいプロジェクトの構成] ページで、[プロジェクト名] ボックスに「StringLibraryTest」と入力します。 [次へ] を選びます。
[追加情報] ページで、[Framework] ボックスの中から .NET 8 を選択します。 次に、[の作成] を選択します。
Visual Studio によってプロジェクトが作成され、クラス ファイルが次のコードでコード ウィンドウに開かれます。 使用する言語で表示されていない場合は、ページの上部にある言語セレクターを変更します。
namespace StringLibraryTest; [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { } }
Imports Microsoft.VisualStudio.TestTools.UnitTesting Namespace StringLibraryTest <TestClass> Public Class UnitTest1 <TestMethod> Sub TestSub() End Sub End Class End Namespace
単体テストのテンプレートで作成されたソース コードにより、次の処理が行われます。
- 単体テストで使用される型が含まれた Microsoft.VisualStudio.TestTools.UnitTesting 名前空間がインポートされます。 C# では、GlobalUsings.cs の
global using
ディレクティブを介して名前空間がインポートされます。 - TestClassAttribute 属性が
UnitTest1
クラスに適用されます。 - TestMethodAttribute 属性を適用して、C# では
TestMethod1
を、また Visual Basic ではTestSub
が定義されます。
[TestClass]でタグ付けされたテスト クラスの [TestMethod] でタグ付けされた各テスト メソッドが、単体テスト実行時に自動実行されます。
- 単体テストで使用される型が含まれた Microsoft.VisualStudio.TestTools.UnitTesting 名前空間がインポートされます。 C# では、GlobalUsings.cs の
プロジェクト参照を追加する
テスト プロジェクトが StringLibrary
クラスと連動するように、StringLibraryTest プロジェクトに StringLibrary
プロジェクトへの参照を追加します。
ソリューション エクスプローラーで [StringLibraryTest] プロジェクトの [依存関係] ノードを右クリックし、コンテキスト メニューの [プロジェクト参照の追加] を選択します。
[参照マネージャー] ダイアログボックスで、[プロジェクト] ノードを展開し、[StringLibrary] の横にあるボックスを選択します。
StringLibrary
アセンブリに参照を追加すると、コンパイラが StringLibraryTest プロジェクトをコンパイル中に、StringLibrary メソッドを見つけることができるようになります。OK を選択します。
単体テスト メソッドの追加と実行
Visual Studio で単体テストを実行すると、TestClassAttribute 属性でマークされたクラス内で、TestMethodAttribute 属性でマークされた各メソッドが実行されます。 テスト メソッドは、最初の失敗が検出されたとき、またはそのメソッドに含まれているすべてのテストが成功したときに終了します。
一般的なテストでは、Assert クラスのメンバーが呼び出されます。 多くのアサート メソッドは最低 2 つのパラメーターを含んでいます。1 つは予期されるテスト結果、もう 1 つは実際のテスト結果です。 次の表に、Assert
クラスの頻繁に呼び出されるメソッドをいくつか示します。
Assert メソッド | Function |
---|---|
Assert.AreEqual |
2 つの値または 2 つのオブジェクトが等しいことを確認します。 値またはオブジェクトが等しくない場合、アサートは失敗します。 |
Assert.AreSame |
2 つのオブジェクト変数が同じオブジェクトを参照していることを確認します。 変数が別々のオブジェクトを参照している場合、アサートは失敗します。 |
Assert.IsFalse |
条件がfalse であることを検証します。 条件が true の場合、アサートは失敗します。 |
Assert.IsNotNull |
オブジェクトが null でないことを確認します。 オブジェクトが null である場合、アサートは失敗します。 |
また、テスト メソッドで Assert.ThrowsException (MSTest 3.8 以降を使用している場合は Assert.Throws
および Assert.ThrowsExactly
) メソッドを使用して、スローする必要がある例外の種類を示すこともできます。 指定した例外がスローされない場合、テストは失敗します。
StringLibrary.StartsWithUpper
メソッドのテストでは、大文字で始まる文字列を多く用意します。 これらの場合ではメソッドが true
を返すと予測されるので、Assert.IsTrue メソッドを呼び出すことができます。 同様に、大文字以外で始まる文字列を多く用意します。 これらの場合ではメソッドが false
を返すと予測されるので、Assert.IsFalse メソッドを呼び出すことができます。
ライブラリ メソッドは文字列を処理するため、空の文字列 (String.Empty
) (文字がなく Length が 0 である有効な文字列)、および初期化されていない null
文字列を正しく処理することも確認します。 しかし、StartsWithUpper
を静的メソッドとして直接呼び出して、単一の String 引数を渡すこともできます。 または、null
に割り当てられた string
変数の拡張メソッドとして StartsWithUpper
を呼び出すこともできます。
メソッドを 3 つ定義します。これらのメソッドでは、文字列配列の各要素に対して Assert メソッドが呼び出されます。 メソッドのオーバーロードを呼び出します。これにより、テストが失敗した場合に表示されるエラー メッセージを指定できます。 このメッセージによって、エラーの原因となった文字列が識別されます。
テスト メソッドを作成するには
UnitTest1.cs または UnitTest1.vb コード ウィンドウで、コードを次のコードに置き換えます。
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)); } } } }
Imports Microsoft.VisualStudio.TestTools.UnitTesting Imports UtilityLibraries Namespace StringLibraryTest <TestClass> Public Class UnitTest1 <TestMethod> Public Sub TestStartsWithUpper() ' Tests that we expect to return true. Dim words() As String = {"Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"} For Each word In words Dim result As Boolean = word.StartsWithUpper() Assert.IsTrue(result, $"Expected for '{word}': true; Actual: {result}") Next End Sub <TestMethod> Public Sub TestDoesNotStartWithUpper() ' Tests that we expect to return false. Dim words() As String = {"alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство", "1234", ".", ";", " "} For Each word In words Dim result As Boolean = word.StartsWithUpper() Assert.IsFalse(result, $"Expected for '{word}': false; Actual: {result}") Next End Sub <TestMethod> Public Sub DirectCallWithNullOrEmpty() ' Tests that we expect to return false. Dim words() As String = {String.Empty, Nothing} For Each word In words Dim result As Boolean = StringLibrary.StartsWithUpper(word) Assert.IsFalse(result, $"Expected for '{If(word Is Nothing, "<null>", word)}': false; Actual: {result}") Next End Sub End Class End Namespace
TestStartsWithUpper
メソッドの大文字のテストには、ギリシャ語の大文字のアルファ (U+0391) とキリル文字の大文字 EM (U+041C) が含まれています。TestDoesNotStartWithUpper
メソッドの小文字のテストには、ギリシャ語の小文字のアルファ (U+03B1) とキリル文字の小文字 Ghe (U+0433) が含まれています。メニュー バーで、[ファイル]>[名前を付けて UnitTest1.cs を保存] または [ファイル]>[名前を付けて UnitTest1.vb を保存] の順に選択します。 [名前を付けてファイルを保存] ダイアログで、[保存] ボタンの横にある矢印を選択して、[エンコード付きで保存] を選択します。
[名前を付けて保存の確認] ダイアログ ボックスで、[はい] ボタンを選択してファイルを保存します。
[保存オプションの詳細設定] ダイアログの [エンコード] ドロップダウン リストから [Unicode (UTF-8 シグネチャ付き) - コードページ 65001] を選択し、[OK] の順に選択します。
UTF8 でエンコードされたファイルにソース コードを保存できなかった場合、ASCII ファイルとして保存される場合があります。 その場合は、ランタイムで ASCII 範囲外の UTF8 文字が正確にデコードされず、テスト結果が正確でなくなります。
メニュー バーで [テスト]>[すべてのテストを実行する] を選択します。 テスト エクスプローラーの ウィンドウが開かない場合は、[テスト>テスト エクスプローラー]を選んで開いてください。 3 つのテストが [成功したテスト] セクションに表示され、[概要] セクションにはテストの実行結果が表示されています。
テストが合格したテスト エクスプローラー ウィンドウで
テストの失敗の処理
テスト駆動開発 (TDD) を行っている場合、最初にテストを作成すると、1 回目のテスト実行は失敗します。 その後、テストを成功させるコードをアプリに追加します。 このチュートリアルでは、検証するアプリ コードを記述した後にテストを作成したため、テストが失敗することはありませんでした。 テストの失敗が予想されるときにテストが失敗することを検証するには、テスト入力に無効な値を追加します。
TestDoesNotStartWithUpper
メソッドのwords
配列を変更し、文字列 "Error" を含めます。 ソリューションをビルドし、テストを実行するときに、Visual Studio では、自動的に開いているファイルが保存されるため、ファイルは保存する必要はありません。string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство", "1234", ".", ";", " " };
Dim words() As String = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство", "1234", ".", ";", " " }
メニューバーから テスト>すべてのテスト を選択して、テストを実行します。 [テスト エクスプローラー] ウィンドウに、テストが 2 つ成功し、1 つ失敗したことが示されます。
失敗したテストを選択し、
TestDoesNotStartWith
を実行します。テスト エクスプローラーの ウィンドウには、assert によって生成されたメッセージ「Assert.IsFalse に失敗しました」が表示されます。 Expected for 'Error': false; actual: True" が表示されます。 エラーのため、配列内の "Error" の後ろの文字列はテストされませんでした。
手順 1 で追加した文字列 "Error" を削除します。 テストを再実行すると、テストは成功します。
ライブラリのリリース バージョンのテスト
これで、ライブラリのデバッグ ビルドを実行したときにすべてのテストが成功したので、さらにライブラリのリリース ビルドに対してテストを行います。 コンパイラの最適化などのさまざまな要因により、デバッグ ビルドとリリース ビルドとでは動作が異なる場合があります。
リリース ビルドをテストするには、次の操作を行います。
Visual Studio のツールバーで、ビルド構成を [デバッグ] から [リリース] に変更します。
ソリューション エクスプローラーで [StringLibrary] プロジェクトを右クリックし、コンテキスト メニューの [ビルド] を選択し、ライブラリを再コンパイルします。
ビルド コマンド を使用して StringLibrary コンテキスト メニューを
する メニューバーから [テスト] を選び、[すべてのテストの実行]> を実行して、単体テストを行います。 テストが成功します。
テストのデバッグ
IDE として Visual Studio を使用する場合は、「チュートリアル: Visual Studio を使用して .NET コンソール アプリケーションをデバッグする」に示されているものと同じプロセスを使用し、単体テスト プロジェクトを使ってコードをデバッグできます。 ShowCase アプリ プロジェクトを開始する代わりに、StringLibraryTests プロジェクトを右クリックし、コンテキスト メニューから [テストのデバッグ] を選択します。
Visual Studio により、デバッガーがアタッチされた状態でテスト プロジェクトが開始されます。 実行は、テスト プロジェクトまたは基になるライブラリ コードに追加したブレークポイントで停止します。
その他の技術情報
次のステップ
このチュートリアルでは、クラス ライブラリの単体テストを行いました。 ライブラリをパッケージとして NuGet に発行した場合、他のユーザーもそれを使用できます。 方法については、次の NuGet のチュートリアルに従ってください。
ライブラリを NuGet パッケージとして発行した場合、他のユーザーもそれをインストールして使用できます。 方法については、次の NuGet のチュートリアルに従ってください。
ライブラリはパッケージとして配布する必要はありません。 それが使用されるコンソール アプリにバンドルすることができます。 コンソール アプリを発行する方法については、このシリーズの前のチュートリアルを参照してください。
.NET