【Unity】Unity Test Runner入門 - インストールから基本的な使い方・注意点まとめ

Unity Test Runnerの基本的な使い方と使う上での注意点をまとめました。

Unity 2019.2.6
Test Framework 1.0.18

インストール

Unity2019.1まではTest RunnerがUnityエディタに組み込まれているのでインストールする必要はありません。
その場合はこの説は飛ばして次節から読み進めてください。

Unity2019.2からはPackage化されたため、Package Managerからインストールする必要があります。
Package ManagerからTest Frameworkと検索してインストールします。

f:id:halya_11:20191024232434p:plain

Package Managerの使い方は以下の記事にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

起動とセットアップ

インストールが終わったらWindow > General > TestRunnerからTest Runnerを起動します。
起動したら以下の画面になるので、Create EditMode Test Assembly Folderをクリックします。

f:id:halya_11:20191025000029p:plain

フォルダが一つ作成されるので、変えたければ好きな名前に変えておきます。

f:id:halya_11:20191025000349p:plain

このフォルダまたはフォルダの中にあるファイルを選択した状態でTest Runnerに戻ります。
すると先ほどのボタンが消えて、非アクティブだったボタンがアクティブになっていることが確認できます。

f:id:halya_11:20191025000559p:plain

これでセットアップは完了です。
ちなみに、これはNUnitという外部のフレームワークを参照するための手順です。

テスト用スクリプトを作る

それでは次にテスト用のスクリプトを作成します。
Test RunnerウィンドウからCreate Test Script in current folderをクリックします。

f:id:halya_11:20191025001359p:plain

するとスクリプトが作られるのに適当に名前を変えておきます。
このスクリプトにはすでに二つサンプルのテストが書かれているのでそれらが一覧に表示されます。

f:id:halya_11:20191025002231p:plain

試しにRun Allをクリックするとすべてのテストが正常に完了することが確認できます。

f:id:halya_11:20191025001703p:plain

ちなみにテスト用のスクリプトAssets/Create/Testing/C# Test Scriptからも作れます。

f:id:halya_11:20191025001916p:plain

テストを書く

それでは実際にテストを書いてみます。
まず、1フレームで終わるテストはTestアトリビュートを付けたメソッドとして定義します。
そしてAssert.Thatメソッドに条件式を入れてテスト処理を書きます。

using NUnit.Framework;

namespace Tests
{
    public class Example
    {
        // Testアトリビュートを付ける
        [Test]
        public void ExampleTest()
        {
            // 条件式がtrueだったら成功
            Assert.That(1 < 10);
        }
    }
}

また、複数フレームにまたがる処理をテストするにはUnityTestアトリビュートを付けたメソッドを定義します。
戻り値をIEnumeratorとし、yield return null;でフレームを進めます。

using NUnit.Framework;
using System.Collections;
using UnityEngine.TestTools;

namespace Tests
{
    public class Example
    {
        // UnityTestアトリビュートを付ける
        [UnityTest]
        public IEnumerator ExampleTestEnumerator()
        {
            Assert.That(1 < 10);
            // yield return nullで1フレーム進める
            yield return null;
            Assert.That(2 < 10);
            yield return null;
            Assert.That(3 < 10);
        }
    }
}

Assert.Thatの書き方

さて前節では判定にAssert.That()を使いました。
実はこれには多くのオーバーロードがあり、それらを使うことでより柔軟な条件を判定できます。
主要なものを挙げてみると以下のような感じです。

// 条件式がtrueだったら成功
Assert.That(1 < 10);
            
// 1個目の引数が2個目より小さければ成功
Assert.That(10, Is.LessThan(100));

// 1個目の引数が2個目の引数の範囲内なら成功
Assert.That(10, Is.InRange(0, 100));

// 1個めの引数の文字列が2個目の文字列で始まっていたら成功
Assert.That("Example", Does.StartWith("Ex"));

// 1個めの引数の文字列に2個目の文字列が含まれていたら成功
Assert.That("Example", Does.Contain("xamp"));

// 1個めの引数の文字列が2個目の文字列で終わっていたら成功
Assert.That("Example", Does.EndWith("ple"));

// 1個めの引数の文字列が2個目の正規表現にマッチしたら成功
Assert.That("Example", Does.Match("Ex*"));

詳しくはNUnitのドキュメントに書かれています。
このあたりは必要に応じて徐々に覚えていけばいいかと思います。

github.com

ちなみにAssert.True()とかAssert.AreEqual()とかも使えますがちょっと古い書き方(Classic Model)です。

github.com

Play Modeでもテストする

さてここまではUnityを再生しない状態(Edit Mode)でのテストを書いてきましたが、再生中にテストすることもできます。
Play Modeの場合もEdit Modeと同様にテスト用のフォルダを作りますが、
その際にPlayModeタブを選択してからフォルダ作成ボタンを押します。

f:id:halya_11:20191025011512p:plain

あとはEdit Modeと同様にスクリプトを作成しテスト処理を書くだけです。

f:id:halya_11:20191025011643p:plain

違いとして、テストをRunした時にUnityが再生され、IEnumeratorはコルーチンによって処理されます。
また、Run all in player([platform name])をクリックすると、選択中のプラットフォームのビルドが走って、実機でテストが実行できます。

注意点: アセンブリへのアクセス

さて実際にはテストコードは自身で書いたプログラムを参照する必要があります。
この際、参照したいアセンブリを、前述の手順で自動生成されたフォルダ内にある
Assembly Definition Fileに設定する必要があります(本筋から逸れるので詳細は割愛します)。

f:id:halya_11:20191025012235p:plain

また特に注意が必要なのが、UnityのデフォルトアセンブリであるAssembly-CSharp.dllにアクセスしたい場合です。
この場合にはTest Runnerの左上のメニューからEnable playmode tests for all assembliesを選択する必要があります。

f:id:halya_11:20191025012606p:plain

そしてさらにこの状態から、自動生成されたAssembly Definition Fileを削除します。

するとAssembly-CSharp.dllにアクセスできるようになります。
ただしこれを有効にすると、追加のアセンブリがビルドに含まれてしまうのでビルド時間とサイズが大きくなるという欠点があります。

Note: Enabling Play Mode tests for all assemblies includes additional assemblies in your project build, which can increase the project’s size as well as the build time.
Workflow: How to create a Play Mode test | Package Manager UI website

さらにリリース時にはテストが含まれないようにする必要も出てきます。

You must remove these tests after the test run so that Unity does not add them to the final Player build.
Workflow: How to create a Play Mode test | Package Manager UI website

これらのことから、テスト対象をAssembly-CSharp.dllに含めるのはあまり推奨される方法では無さそうです。
テストを考えるためには、自分で書いたコードにもしっかりAssembly Definition Fileを設定して参照関係を構築する設計が必要そうです。

参考

docs.unity3d.com

github.com

qiita.com