ようやく重い腰を上げて手元のUnity 2017.4プロジェクトを2018.3に移行したので*1、何番煎じかわからないけどテスト(Unit tests)まわりについてまとめ。
Test Runnerウィンドウ
2017ではメニューのWindow直下にあった"Test Runner"ですが、Window > General > Test Runnerに移動されました。
Edit mode Tests
2017.4までは、EditModeで実行するテストコードはAssets/**/Editor/**/
下にあればよかったのですが、2018では条件が増えています。
例えばAssets/Xxx/Editor/
のようなフォルダ階層でXxx
下にAssembly Definition(以下asmdef)ファイルを置いてしまうと、Editor
まで同じアセンブリに含まれてしまいます。
Xxx/Editor
下にEdit mode Testsがある場合はXxx/Editor
直下にもうひとつadmdefファイルを作り*2、"Test Assemblies"と"Editor"の2つのチェックボックスをonにする必要があります。
なお、Edit modeでは[UnityTest]
属性をつけたテストはEditorApplication.update
コールバックループで実行されるという点は2017も2018も同様です。
Play mode Tests
2017ではPlay modeでテストを実行するには”Enable playmode tests”をクリックしてから再起動する手順が必要でしたが、2018では不要になっています。
代わりに、テストコードは任意のフォルダ下に置き、そこにadmdefファイルを作り、"Test Assemblies"チェックボックスをonにする必要があります。
なお、Play modeでは[UnityTest]
属性をつけたテストはコルーチンで実行されるという点は2017も2018も同様です。
Enable playmode tests for all assemblies
もし、Play modeのテストコードを容易に移動できない、asmdefによってアセンブリを分けることが困難といった場合、Test Runnerウィンドウ右上のハンバーガーメニューから"Enable playmode tests for all assemblies"をクリックして有効にすることで、Unity 2017のようにモードを切り替えてPlay mode Testsを実行することができるようです(未確認)。
ただし、このままではビルドに追加のアセンブリが含まれるため、プロジェクトのサイズとビルド時間が長くなってしまいますので、ビルドを行なうときにはDisableに戻すべきです。
アセンブリの依存関係
Assembly Definitionファイル(以下asmdef)はUnity 2017.3から導入された機能で、アセンブリを小分けすることでプロジェクトのビルド時間を節約する効果があります。
Unity 2018からはテストコードは専用のアセンブリ("Test Assemblies"チェックボックスをonにしたもの)に属する必要が生じたため、テストコードのasmdefからSUT(system under test: テスト対象)ほか使用しているasmdefを参照する旨を"Assembly Definition References"に設定する必要があります。
下図はSUTである"SUTClient"と、"UniRx"に依存している例です。
Internalの扱い
C#では、Internal
アクセス修飾子をつけたclass/methodは同一アセンブリ内からのみ参照できます。Unity 2018でテストコードが別アセンブリになったことによって、そのままではInternalなclass/methodのテストを書くことができません*3。
これに対し、参照される側(SUT)の中に以下のコードを書くことで、指定したアセンブリに対してInternalなclass/methodを公開することができます。
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
[assembly: InternalsVisibleTo("SampleTestsAssembly")]
""の中には、公開するアセンブリ(この文脈上はテストコードのアセンブリ)名を書きます。"Assembly-CSharp-Editor"はUnityエディタです。
なお、このコードはアセンブリ内のどのファイルに書いても良いようなのですが、過去の経緯から"AssemblyInfo.cs"というファイルに書くことが多い? ようです。
おまけのTips
Time.timeScaleでPlay mode testの実行速度上げられるの知らなかった
— Koji Hasegawa (@nowsprinting) 2019年2月20日
Testing Test-Driven Development with the Unity Test Runner – Unity Blog https://t.co/Yt4LQ4ihL6