チュートリアル: UWP アプリ用の単体テストの作成および実行
この記事では、Visual Studio でユニバーサル Windows プラットフォーム (UWP) アプリを単体テストする方法について説明します。 Visual Studio には、C#、Visual Basic、C++ 用の UWP 単体テスト プロジェクト テンプレートが用意されています。 UWP アプリの開発の詳細については、UWP アプリの概要に関するページを参照してください。
この記事では、UWP アプリの C# クラスを作成して単体テストする例について説明します。 この例では、テスト駆動開発を使って特定の動作を検証するテストを作成した後、そのテストに成功するコードを記述します。
単体テスト プロジェクトを作成して実行する
以下の手順は、UWP アプリの単体テスト プロジェクトを作成して実行する方法を説明しています。
UWP 単体テスト プロジェクトを作成する
Visual Studio の [スタート] ウィンドウで、[新しいプロジェクトの作成] を選択します。
[新しいプロジェクトの作成] ページの検索ボックスに、「単体テスト」と入力します。 テンプレートの一覧が単体テスト プロジェクトに絞り込まれます。
C# または Visual Basic に対して [単体テスト アプリ (ユニバーサル Windows)] テンプレートを選択し、[次へ] を選択します。
必要に応じて、プロジェクトまたはソリューションの名前と場所を変更し、[作成] を選択します。
必要に応じて、ターゲットと最小プラットフォーム バージョンを変更し、[OK] を選択します。
Visual Studio によってテスト プロジェクトが作成され、Visual Studio のソリューション エクスプローラーで開かれます。
Visual Studio の [スタート] ウィンドウで、[新しいプロジェクトの作成] を選択します。
[新しいプロジェクトの作成] ページの検索ボックスに、「単体テスト」と入力します。 テンプレートの一覧が単体テスト プロジェクトに絞り込まれます。
C# または Visual Basic に対して [単体テスト アプリ (ユニバーサル Windows)] テンプレートを選択し、[次へ] を選択します。
必要に応じて、プロジェクトまたはソリューションの名前と場所を変更し、[作成] を選択します。
必要に応じて、ターゲットと最小プラットフォーム バージョンを変更し、[OK] を選択します。
Visual Studio によってテスト プロジェクトが作成され、Visual Studio のソリューション エクスプローラーで開かれます。
プロジェクトのアプリケーション マニフェストを編集する
ソリューション エクスプローラーで、Package.appxmanifest ファイルを右クリックし、[開く] を選択します。
マニフェスト デザイナーで、[機能] タブを選択します。
[機能] の一覧から、コードと単体テストに必要な機能を選択します。 たとえば、コードとその単体テストでインターネットにアクセスする必要がある場合は、[インターネット] チェックボックスをオンにします。
単体テストが正しく動作するために必要な機能のみを選択してください。
UWP アプリを単体テストするコードを追加する
Visual Studio コード エディターで単体テストのコード ファイルを編集し、テストに必要なアサートとロジックを追加します。 例については、この記事で後述する「C# クラスの単体テスト」を参照してください。
テスト エクスプローラーを使って単体テストを実行する
ソリューションをビルドし、テスト エクスプローラーを使って単体テストを実行します。
Visual Studio の [テスト] メニューで、[テスト エクスプローラー] を選択します。 [テスト エクスプローラー] ウィンドウが開きます。
[テスト エクスプローラー] で、[すべて実行] アイコンを選択します。 UWP プロジェクトでテストを検出するには、[すべて実行] を使う必要があります。
ソリューションがビルドされ、単体テストが実行されます。 テストの実行後、そのテストが [テスト エクスプローラー] のテスト リストに表示され、結果と実行時間に関する情報が表示されます。
また、[テスト エクスプローラー] では、個々のテストを選択し、右クリックしてテストを [実行] または [デバッグ] したり、[テストに移動] でテスト コードを開いたりすることができます。 上部のメニューからは、テストをグループ化したり、テストをプレイリストに追加したり、テスト オプションを開いたりすることができます。
ソリューションをビルドし、テスト エクスプローラーを使って単体テストを実行します。
Visual Studio の [テスト] メニューで、[テスト エクスプローラー] を選択します。 [テスト エクスプローラー] ウィンドウが開きます。
[テスト エクスプローラー] で、[すべて実行] アイコンを選択します。 UWP プロジェクトでテストを検出するには、[すべて実行] を使う必要があります。
ソリューションがビルドされ、単体テストが実行されます。 テストの実行後、そのテストが [テスト エクスプローラー] のテスト リストに表示され、結果と実行時間に関する情報が表示されます。
また、[テスト エクスプローラー] では、個々のテストを選択し、右クリックしてテストを [実行] または [デバッグ] したり、[テストに移動] でテスト コードを開いたりすることができます。 上部のメニューからは、テストをグループ化したり、テストをプレイリストに追加したり、テスト [オプション] を開いたりすることができます。
C# クラスの単体テスト
安定した一連の適切な単体テストにより、コードを変更したときにバグが生じていないという信頼性が高まります。 以下の例では、UWP アプリの C# クラスの単体テストを作成する 1 つ方法について説明します。 この例では、テスト駆動開発 を使って特定の動作を検証するテストを作成した後、そのテストに成功するコードを記述します。
Maths コード プロジェクトの例では、Rooter クラスで、数値の平方根の推定値を計算する関数を実装します。 RooterTests プロジェクトでは、Rooter クラスの単体テストを行います。
ソリューションとプロジェクトを作成する
UWP アプリ プロジェクトを作成する:
- Visual Studio の [ファイル] メニューから、[新規作成] を選択します。
- [新しいプロジェクトの作成] ページで、検索ボックスに 空のアプリ と入力し、C# の [空のアプリ (ユニバーサル Windows)] プロジェクト テンプレートを選択します。
- [新しいプロジェクトの構成] ページで、プロジェクトに「Maths」という名前を付けて、[作成] を選択します。
- 必要に応じて、ターゲットと最小プラットフォーム バージョンを変更し、[OK] を選択します。 Visual Studio によってプロジェクトが作成され、ソリューション エクスプローラーで開かれます。
単体テスト プロジェクトを作成する:
- ソリューション エクスプローラーで、Maths ソリューションを右クリックして、[追加]>[新しいプロジェクト] の順に選択します。
- [新しいプロジェクトの追加] ページで、検索ボックスに 単体テスト と入力し、C# の [単体テスト アプリ (ユニバーサル Windows)] プロジェクト テンプレートを選択します。
- テスト プロジェクトに RooterTests という名前を付け、[作成] を選択します。
- 必要に応じて、ターゲットと最小プラットフォーム バージョンを変更し、[OK] を選択します。 ソリューション エクスプローラーの Maths ソリューションの下に RooterTests プロジェクトが表示されます。
テスト エクスプローラーでテストの実行を確認する
Assert クラスには、テスト メソッドで結果を確認するために使用するいくつかの静的メソッドが用意されています。
ソリューション エクスプローラーで、RooterTests プロジェクトの UnitTest.cs ファイルを選択します。
TestMethod1
に次のコードを挿入します。[TestMethod] public void TestMethod1() { Assert.AreEqual(0, 0); }
テスト エクスプローラーで [すべてのテストを実行する] を選択します。
テスト プロジェクトがビルドされて実行され、[成功したテスト] の下にテストが表示されます。 右側の [グループの概要] ペインに、テストの詳細が表示されます。
アプリ プロジェクトにクラスを追加する
ソリューション エクスプローラーで、Maths プロジェクトを右クリックし、[追加]>[クラス] を選びます。
クラス ファイルに「Rooter.cs」という名前を付け、[追加] を選択します。
コード エディターで、Rooter.cs ファイルの
Rooter
クラスに次のコードを追加します。public Rooter() { } // estimate the square root of a number public double SquareRoot(double x) { return 0.0; }
Rooter
クラスは、コンストラクターとSquareRoot
エスティメーターのメソッドを宣言します。SquareRoot
メソッドは、基本的なテスト セットアップをテストするための最小限の実装です。Rooter
クラスの宣言でinternal
キーワードをpublic
に変更して、テスト コードからアクセスできるようにします。public class Rooter
ソリューション エクスプローラーで、Maths プロジェクトを右クリックし、[追加]>[クラス] を選びます。
クラス ファイルに「Rooter.cs」という名前を付け、[追加] を選択します。
コード エディターで、Rooter.cs ファイルの
Rooter
クラスに次のコードを追加します。public Rooter() { } // estimate the square root of a number public double SquareRoot(double x) { return 0.0; }
Rooter
クラスは、コンストラクターとSquareRoot
エスティメーターのメソッドを宣言します。SquareRoot
メソッドは、基本的なテスト セットアップをテストするための最小限の実装です。Rooter
クラスの宣言にpublic
キーワードを追加して、テスト コードからアクセスできるようにします。public class Rooter
テスト プロジェクトからの参照をアプリ プロジェクトに追加する
ソリューション エクスプローラーで、RooterTests プロジェクトを右クリックし、[追加]>[参照] を選びます。
[参照マネージャー - RooterTests] ダイアログ ボックスで、[プロジェクト] を展開し、Maths プロジェクトを選択します。
[OK] を選択します。
次の
using
ステートメントを、UnitTest.cs のusing Microsoft.VisualStudio.TestTools.UnitTesting;
行の後に追加します。using Maths;
ソリューション エクスプローラーで、RooterTests プロジェクトを右クリックし、[追加]>[参照] を選びます。
[参照マネージャー - RooterTests] ダイアログ ボックスで、[プロジェクト] を展開し、Maths プロジェクトを選択します。
[OK] を選択します。
次の
using
ステートメントを、UnitTest.cs のusing Microsoft.VisualStudio.TestTools.UnitTesting;
行の後に追加します。using Maths;
アプリの関数を使うテストを追加する
UnitTest.cs に次のテスト メソッドを追加します。
[TestMethod] public void BasicTest() { Maths.Rooter rooter = new Rooter(); double expected = 0.0; double actual = rooter.SquareRoot(expected * expected); double tolerance = .001; Assert.AreEqual(expected, actual, tolerance); }
新しいテストが、ソリューション エクスプローラーと、テスト エクスプローラーの [テストを実行しない] ノードに表示されます。
"ペイロードに含まれている複数のファイルで同じターゲット パスが指定されています" エラーを回避するには、ソリューション エクスプローラーで、Maths プロジェクトの下の [プロパティ] ノードを展開し、Default.rd.xml ファイルを削除します。
すべてのファイルを保存します。
テストの実行
[テスト エクスプローラー] で、[すべてのテストを実行] アイコンを選択します。 ソリューションがビルドされ、テストが実行されて成功します。
[テスト エクスプローラー] で、[すべてのテストを実行] アイコンを選択します。 ソリューションがビルドされ、テストが実行されて成功します。
テストの実行時に、エンティティの重複エラーが発生した場合、ランタイム ディレクティブ ファイル Properties\Default.rd.xml
をテスト プロジェクトから削除して、再試行します。
テストおよびアプリのプロジェクトを設定し、アプリ プロジェクトで関数を呼び出すテストを実行できることを確認しました。 これで、実際のテストとコードを記述できます。
テストを追加して成功させる
成功したテストは変更しないことをお勧めします。 その代わりに、新しいテストを追加します。 一度に 1 つずつテストを追加しながらコードを開発し、各繰り返しの後にすべてのテストが成功するようにします。
RangeTest
という名前の新しいテストを UnitTest.cs に追加します。[TestMethod] public void RangeTest() { Rooter rooter = new Rooter(); for (double v = 1e-6; v < 1e6; v = v * 3.2) { double expected = v; double actual = rooter.SquareRoot(v*v); double tolerance = expected/1000; Assert.AreEqual(expected, actual, tolerance); } }
RangeTest テストを実行し、失敗することを確認します。
ヒント
テスト駆動開発では、テストを記述した直後に実行します。 この方法は、絶対に失敗しないテストを記述するという簡単なミスを避けることに役立ちます。
新しいテストが成功するように、アプリ コードを修正します。 Rooter.cs の
SquareRoot
関数を、次のように変更します。public double SquareRoot(double x) { double estimate = x; double diff = x; while (diff > estimate / 1000) { double previousEstimate = estimate; estimate = estimate - (estimate * estimate - x) / (2 * estimate); diff = Math.Abs(previousEstimate - estimate); } return estimate; }
[テスト エクスプローラー] で、[すべてのテストを実行] アイコンを選択します。 3 つのテストはすべて成功しました。
RangeTest
という名前の新しいテストを UnitTest.cs に追加します。[TestMethod] public void RangeTest() { Rooter rooter = new Rooter(); for (double v = 1e-6; v < 1e6; v = v * 3.2) { double expected = v; double actual = rooter.SquareRoot(v*v); double tolerance = expected/1000; Assert.AreEqual(expected, actual, tolerance); } }
RangeTest テストを実行し、失敗することを確認します。
ヒント
テスト駆動開発では、テストを記述した直後に実行します。 この方法は、絶対に失敗しないテストを記述するという簡単なミスを避けることに役立ちます。
新しいテストが成功するように、アプリ コードを修正します。 Rooter.cs の
SquareRoot
関数を、次のように変更します。public double SquareRoot(double x) { double estimate = x; double diff = x; while (diff > estimate / 1000) { double previousEstimate = estimate; estimate = estimate - (estimate * estimate - x) / (2 * estimate); diff = Math.Abs(previousEstimate - estimate); } return estimate; }
[テスト エクスプローラー] で、[すべてのテストを実行] アイコンを選択します。 3 つのテストはすべて成功しました。
コードをリファクタリングする
このセクションでは、アプリとテスト コードの両方をリファクターし、テストを再実行して、まだ成功することを確認します。
平方根の推定を簡素化する
Rooter.cs で、次の行を変更し、
SquareRoot
関数の中央にある計算を簡略化します。estimate = estimate - (estimate * estimate - x) / (2 * estimate);
終了
estimate = (estimate + x/estimate) / 2.0;
すべてのテストを実行して、回帰が発生していないことを確認します。 テストはすべて成功するはずです。
重複するテスト コードを削除する
RangeTest
メソッドでは、Assert メソッドに渡される tolerance
変数の分母がハードコーディングされています。 同じ許容値の計算を使ったテストをさらに追加する予定がある場合、複数の場所でハードコーディングされた値を使うと、コードの保守が難しくなります。 代わりに、許容値を計算するプライベート ヘルパー メソッドを UnitTest1
クラスに追加して、そのメソッドを RangeTest
から呼び出すことができます。
ヘルパー メソッドを追加するには、UnitTest.cs で:
次のメソッドを
UnitTest1
クラスに追加します:private double ToleranceHelper(double expected) { return expected / 1000; }
RangeTest
で、次の行を変更します。double tolerance = expected/1000;
終了
double tolerance = ToleranceHelper(expected);
RangeTest テストを実行して、まだ成功することを確認します。
ヒント
テスト クラスにヘルパー メソッドを追加し、そのヘルパー メソッドをテスト エクスプローラーの一覧に表示したくない場合は、メソッドに TestMethodAttribute 属性を追加しないでください。