Unity Test Framework バージョン 1.3 から使えるasync/awaitを使ったテスト
UnityTest属性とNUnitの一部属性は併用できない
次の属性はUnityTest属性と組み合わせて使用できませんでしたが、Asyncテストでは使用できます。
TestCase属性
TestCaseSource属性
Pairwise属性
Sequential属性
引用元: Unity Test Frameworkの非同期テストで できること/ できないこと - やらなイカ?
Unityが提供する [UnityTest]
属性は、テストメソッドをコルーチンとして実行するためのアトリビュートです。一方、NUnitが提供する [TestCase]
や [TestCaseSource]
などのパラメータ化テスト用アトリビュートは、基本的に void
メソッドで使用する想定になっています。そのため、 [UnityTest]
と組み合わせて使用すると、以下のようなエラーが発生する場合があります。
[UnityTest]
[TestCaseSource(nameof(SumTestCases))]
public IEnumerator SumTest(int a, int b, int expectedSum)
{
var result = a + b;
Assert.That(result, Is.EqualTo(expectedSum));
yield return null;
}
private static IEnumerable SumTestCases
{
get
{
yield return new TestCaseData(2, 3, 5);
yield return new TestCaseData(4, 6, 10);
yield return new TestCaseData(1, 1, 2);
}
}
実行すると、次のようなメッセージが表示されます。
Method has non-void return value, but no result is expected
[UnityTest]
はコルーチンを返すことが前提であり、 IEnumerator
を返却する構造になっています。一方で、 [TestCaseSource]
はパラメータ化されたテストを実行するにあたり、void
メソッドを想定しているため、両者が衝突する形になります。
async/awaitを使ってエラーを回避する
Unity Test Framework 1.3 以降では、非同期テストがサポートされるようになりました。そのため、 async/await
を使うことで一部のNUnit属性が併用できるようになります。例として、次のように書くとエラーを回避できます。
[Test] // not UnityTest
[TestCaseSource(nameof(SumTestCases))]
public async Task SumTest(int a, int b, int expectedSum) // 帰り値は async Task
{
var result = a + b;
Assert.That(result, Is.EqualTo(expectedSum));
await Task.Delay(10, CancellationToken.None);
}
private static IEnumerable SumTestCases
{
get
{
yield return new TestCaseData(2, 3, 5);
yield return new TestCaseData(4, 6, 10);
yield return new TestCaseData(1, 1, 2);
}
}
async/awaitが使えなかった際の回避策
古いドキュメントなどでは、 [UnityTest]
と [TestCaseSource]
を併用するためのワークアラウンドとして以下のような方法を紹介している場合があります。
[UnityTest]
[TestCaseSource(nameof(SumTestCases))]
public IEnumerator SumTest(int a, int b, int expectedSum)
{
var result = a + b;
Assert.That(result, Is.EqualTo(expectedSum));
yield return null;
}
private static IEnumerable SumTestCases
{
get
{
// null を指定して、テストメソッドは返り値の比較を行わないことを明記
yield return new TestCaseData(2, 3, 5).Returns(null);
yield return new TestCaseData(4, 6, 10).Returns(null);
yield return new TestCaseData(1, 1, 2).Returns(null);
}
}
コルーチンで動作させる場合、 TestCaseData(...).Returns(null)
を使うことでコンパイラやNUnitからの警告を回避しています。しかし、非同期テストが正式にサポートされた現在では、素直に async/await
を使う方がシンプルでおすすめです。
Discussion
Unity Test Framework v1.3からテストメソッドにasync/awaitを使えるようになりました。
なので、TestCase, TestCaseSource属性はこちらで使うのがおすすめです。
詳しくはこちらの記事を参照してください。
コメントありがとうございます! async/awaitが使えることを知らなかったので、その情報で書き直させていただきました。ご指摘大変ありがとうございましたmm