Zenn
🦔

Unity Test Framework バージョン 1.3 から使えるasync/awaitを使ったテスト

2025/02/07に公開
2
1

UnityTest属性とNUnitの一部属性は併用できない

次の属性はUnityTest属性と組み合わせて使用できませんでしたが、Asyncテストでは使用できます。
TestCase属性
TestCaseSource属性
Pairwise属性
Sequential属性

引用元: Unity Test Frameworkの非同期テストで できること/ できないこと - やらなイカ?

Unityが提供する [UnityTest] 属性は、テストメソッドをコルーチンとして実行するためのアトリビュートです。一方、NUnitが提供する [TestCase][TestCaseSource] などのパラメータ化テスト用アトリビュートは、基本的に void メソッドで使用する想定になっています。そのため、 [UnityTest] と組み合わせて使用すると、以下のようなエラーが発生する場合があります。

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
    {
        yield return new TestCaseData(2, 3, 5);
        yield return new TestCaseData(4, 6, 10);
        yield return new TestCaseData(1, 1, 2);
    }
}

実行すると、次のようなメッセージが表示されます。

ErrorMessage
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属性が併用できるようになります。例として、次のように書くとエラーを回避できます。

https://docs.unity3d.com/Packages/com.unity.test-framework@1.3/manual/reference-async-tests.html

非同期を使った正常に動くテスト
[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] を併用するためのワークアラウンドとして以下のような方法を紹介している場合があります。

TestCaseDataでnullを返すことでコルーチンで実行しながらエラーを回避する
    [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 を使う方がシンプルでおすすめです。

参考

1

Discussion

Koji HasegawaKoji Hasegawa

Unity Test Framework v1.3からテストメソッドにasync/awaitを使えるようになりました。
なので、TestCase, TestCaseSource属性はこちらで使うのがおすすめです。

詳しくはこちらの記事を参照してください。
https://www.nowsprinting.com/entry/2023/01/29/010837

masaki morimasaki mori

コメントありがとうございます! async/awaitが使えることを知らなかったので、その情報で書き直させていただきました。ご指摘大変ありがとうございましたmm

ログインするとコメントできます