NUnitを使う上での手順と、要点のまとめです。
紹介する手順は、NUnitのEXEやコンソールではなく、Visual Studio上から実行する方法です。
既にテスト対象のプロジェクトは存在するものとします。
(※ここでは「NUnitProject」とする)
ソリューションエクスプローラーでソリューションを右クリック
↓
追加
↓
新しいプロジェクト
名前はテストされるプロジェクト名 + Tests
などで良いでしょう。
NUnitをVisaul Studio上で実行する場合、下記の2つをインストールする必要があります。
NuGetからサクッとインストールしましょう。
ソリューションエクスプローラーでテストプロジェクトを右クリック
↓
NuGet パッケージの管理
下記の2項目をインストール
※オフライン環境で実施しているため、実際の検索結果は異なります。
そうすると、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);
}
これでテストケースの数だけテストをコピペする必要がなくなり、属性だけ追加すれば良くなります。
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
に変更してください。
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の使い方~注意点でした。
おしまい