Unity公式のユニットテストレームワークであるUnity Test Frameworkパッケージのバージョン1.3では、非同期テスト(以下Asyncテスト)がサポートされました。
改めて、できること/ できないことを確認してまとめました。
できること
非同期(async)メソッドの呼び出し
Test属性のテストにasyncキーワードを付与することで、テストメソッド内でasyncメソッドを呼び、その完了を待つことができます。
また、SetUpおよびTearDown属性も非同期メソッドに付与できます。
ただしUnitySetUp属性とは異なり、SetUp属性によるセットアップメソッドはドメインリロード*1の後に再実行されません。
サンプルコードなどは次の記事を参照してください。
パラメタライズドテスト
次の属性はUnityTest属性と組み合わせて使用できませんでしたが、Asyncテストでは使用できます。
TestCase属性TestCaseSource属性Pairwise属性Sequential属性
これら属性の使いかたについては『Unity Test Framework完全攻略ガイド』の第8章「パラメタライズドテスト」を参照してください。
できないこと
以下は、Unity Test Framework v1.3.2時点での制限事項です。いずれもバグレポート済みで、修正されたら本記事にも反映する予定です。
[2/24追記] Issue Trackerに登録されています(UUM-25085)。 すでにお困りの方も、今はそうでないが将来お困りになる方も、ぜひvoteをお願いします!
併用するとテストが終了しない属性
次の属性を付けたAsyncテストメソッドは終了しなくなります。
MaxTime属性Repeat属性Retry属性
本事象はUnity Test Framework v1.4.5で修正されました
Throws制約による例外の検証
次のようにThrows制約を使用した例外の検証にasyncメソッドを指定すると、テストが終了しなくなります。
[Test] public async Task 非同期メソッドの例外捕捉に制約モデルは使用できない() { Assert.That( async () => await ThrowNewExceptionInMethod(), Throws.TypeOf<ArgumentException>() .And.Message.EqualTo("message!")); }
クラシックモデルAPIのThrowsAsyncも同様です。[11/18訂正]
[Test] public async Task 非同期メソッドの例外捕捉をThrowsAsyncで行なう例() { Assert.ThrowsAsync<ArgumentException>( async () => await ThrowNewExceptionInMethod()); }
今のところ、try-catchで書くしかありません。
[Test] public async Task 非同期メソッドの例外捕捉をTryCatchで行なう例() { try { await ThrowNewExceptionInMethod(); Assert.Fail("例外が出ることを期待しているのでテスト失敗とする"); } catch (ArgumentException expectedException) { Assert.That(expectedException.Message, Is.EqualTo("message!")); } }
タイムアウトが機能しない
デフォルトではテストは3分でタイムアウトし失敗扱いとなりますが、Asyncテストではこれが機能しません。
Timeout属性で時間を指定しても同様です。
タイムアウトの問題はUnity Test Framework v1.3.4で修正されました
WebGLプレイヤーでTask.Delayが終了しない
Play ModeテストをWebGLプレイヤーで実行するとき、await Task.Delay()を引数1以上で呼び出しているとそのテストは終了しなくなります。
async SetUp/TearDownでも同様です。
await UniTask.Delay()は動作しますので、本事象はUniTaskを使用することで回避できます。
Edit ModeテストではTask.Delayが無効
これはそもそもEdit ModeテストがPlayerLoopで動いていないためで、yield returnステートメントにWaitForSecondsなどが指定できないのと同理由と考えられます。
*1:Edit Modeテストでyield return new RecompileScripts()などを実行したときに発生します。詳しくは『Unity Test Framework完全攻略ガイド』の3.3「Edit Modeテスト固有のyield instructions」を参照してください