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」を参照してください