.net

【VisualStudio】NUnitの使い方と注意点

NUnitを使う上での手順と、要点のまとめです。

紹介する手順は、NUnitのEXEやコンソールではなく、Visual Studio上から実行する方法です。


テストプロジェクトの作成

既にテスト対象のプロジェクトは存在するものとします。
(※ここでは「NUnitProject」とする)
 

ソリューションエクスプローラーでソリューションを右クリック

追加

新しいプロジェクト

下記のように「クラスライブラリ」を選択。
クラスライブラリを選択

名前はテストされるプロジェクト名 + Tests

などで良いでしょう。


テストプロジェクトにNUnitをインストール

NUnitをVisaul Studio上で実行する場合、下記の2つをインストールする必要があります。
 

  • NUnit
  • NUnitTestAdapter

NuGetからサクッとインストールしましょう。

ソリューションエクスプローラーでテストプロジェクトを右クリック

NuGet パッケージの管理

下記の2項目をインストール
※オフライン環境で実施しているため、実際の検索結果は異なります。

NuGet機能選択

  • NUnit
  • NUnit3TestAdapter

 
そうすると、Visual Studio上のテストエクスプローラーや、メニュー⇒テストから操作できます。
※ソースを右クリックからの「単体テストの作成」には対応していません。

 
プロジェクトを作成したら、テストプロジェクトの参照に、テスト対象のプロジェクトに追加しましょう。

プロジェクト参照を追加


テストクラスの作成

通常のクラスと同じように、テストプロジェクトにクラスを追加します。

ソリューションエクスプローラーでテストプロジェクトを右クリック

追加

クラス
テストクラス作成

名前はテストされるクラス名 + Test

など、どのクラスを対象としているかわかるものが良いでしょう。

 
クラスを作成したら、↓の2つをusingに追加しましょう。

using NUnitProject;
using NUnit.Framework;

属性

NUnitを使う上で必須の属性は2つ

属性 説明
TestFixture テストクラスにつける
Test テストメソッドにつける

テスト対象のクラス(Class1.cs)

namespace NUnitProject
{
    public class Class1
    {
        private int z = 0;

        public int calc1(int a, int b)
        {
            return a + b;
        }

        private int calc2(int a, int b)
        {
            return a + b - z;
        }
    }
}

テストするクラス(Class1Test.cs)

namespace NUnitProjectTests
{
    [TestFixture]
    class Class1Test
    {
        Class1 target = new Class1();

        [Test]
        public void Calc1Test_01()
        {
            int result = target.calc1(1, 1);
            Assert.AreEqual(2, result);
        }

    }
}

これで、

「メソッド名 or クラス名右クリック」か、

「メニュー⇒テスト」

からテストが実行/デバックできます。

 
ここまでが最低限。
ここからが知っておくと便利な属性

属性 説明
SetUp [Test]属性ごとに直前に実行される
TearDown [Test]属性ごとに直後に実行される
OneTimeSetUp [TestFixture]属性ごとに1度だけ直前に実行される
OneTimeTearDown [TestFixture]属性ごとに1度だけ直後に実行される
TestCase 書いたTestCaseの数だけ変数値を指定してテストする

読んで字のごとく、JUnitにも相当するアノテーションがあるので、説明は不要かと思います。

特筆したいのが、TestCase属性。

通常、Unitテストを書く場合、
数値なら有効範囲値、無効値、有効範囲境界値、無効境界値などの数値を変えてテストしますよね。

その場合テストケースを複数コピペし、値だけ変えると思います。
そのコピペを不要とするのがTestCase属性というわけです。

 
つまり、

        [Test]
        public void Calc1Test_01()
        {
            int result = target.calc1(1, 1);
            Assert.AreEqual(2, result);
        }

        [Test]
        public void Calc1Test_02()
        {
            int result = target.calc1(100, 200);
            Assert.AreEqual(300, result);
        }

が↓になるわけです。

        [TestCase(1, 1, 2)]
        [TestCase(100, 200, 300)]
        public void Calc1Test(int a, int b, int expected)
        {
            int result = target.calc1(a, b);
            Assert.AreEqual(expected, result);
        }

これでテストケースの数だけテストをコピペする必要がなくなり、属性だけ追加すれば良くなります。


privateなメソッドやフィールドのアクセス

NUnitには、MSTestでいうPrivateObjectクラスの代替が存在しません。
private用のオブジェクトが用意されていないのは、NUnitの設計思想に関わってくると思うのですが、
単体だもん、Unitテスト書きたいじゃん。

 
ってわけで一般的にはリフレクションで対応します。
サンプルソースを載せたほうが早いですね。

先ほど載せたClass1.csのprivateなメソッド(Calc2)とフィールド(z)にアクセスします。

        [Test]
        public void Calc2Test()
        {
            int result;
            Type type = target.GetType();
            MethodInfo methodInfo = type.GetMethod("calc2", BindingFlags.NonPublic | BindingFlags.Instance);

            result = (int)methodInfo.Invoke(target, new object[] { 1, 1 });
            Assert.AreEqual(2, result);

            FieldInfo fieldInfo = type.GetField("z", BindingFlags.NonPublic | BindingFlags.Instance);
            fieldInfo.SetValue(target, 100);

            result = (int)methodInfo.Invoke(target, new object[] { 1, 1 });
            Assert.AreEqual(-98, result);
        }

staticなメソッド/フィールドの場合は、
BindingFlags.Instance

BindingFlags.Static
に変更してください。


NUnitを使う上での注意点

属性をつけるメソッドは公開(public)されている必要がある

privateスコープで[Test]属性のメソッドを実行すると↓のような例外となります。

Method is not public

publicに変更して実行してください。

画面クラスの生成方法

これはNUnitと少し離れますが、
画面クラスのメソッドをテストしたい場合に、インスタンスを作成すると↓の例外が出る場合があります。

System.InvalidOperationException:
呼び出しスレッドは、多数の UI コンポーネントが必要としているため、STA である必要があります。

作成するインスタンスは、メインスレッドから作成しろってことですね。
回避方法はインスタンスの生成をSTAのThreadで行うこと。

 
以下、サンプルソース

        public void CreateInstance()
        {
            Form1 form1 = null;
            Thread createInstanceThread = new Thread(new ThreadStart(() => {
                    form1 = new Form1();
                }));
            createInstanceThread.SetApartmentState(ApartmentState.STA);
            createInstanceThread.Start();
            createInstanceThread.Join();
        }

肝は「ApartmentState.STA」を設定すること。
これでインスタンスの作成ができます。

テストケースが見つからない

NUnitを使っているとデバッグ中にブレークポイントに止まらない、という現象に遭遇しました。
よくよく見ると実行すらされていないようで、テストケースが見つからない。
(通常、テストケースとして見つかれば、テストエクスプローラー上にテストケースが表示される)

何がきっかけかはわかりませんが、通常通り使っていていきなりアタッチされなくなったような気がします。

原因は、NUnitTestAdapterの不具合っぽくてユーザーの下のフォルダに正常にアクセスできなくなっている模様。
下記のフォルダを削除後、ソシューションを再起動すると正常に実行できました。

C:\Users\{ユーザー名}\AppData\Local\Temp\VisualStudioTestExplorerExtensions\NUnit3TestAdapter{version}

 
 
以上、NUnitの使い方~注意点でした。

おしまい

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です