NUnitを使用したUnitTestとは別に、Sceneそのものを実行するIntegartion Testがあります。
こちらではUnityのフレームワークに乗って、実際にフレーム単位でテストが進んでいきます。つまり、UnitTestで使えなかったCoroutineやオブジェクトの動作が判定できます。
オブジェクトの衝突テストをしてみる
ひとまず作ってみましょう。
新しいSceneを開き、「Unity Test Tools→Integretion Test Runner」で、Integration Test実行用のウィンドウを開きます。
この「Create」で新しいテストを追加します。
すると「New Test」というオブジェクトと、TestRunnerがHierarchyに追加されます。
このテストオブジェクトにはタイムアウトが設定されていて、制限時間内にIntegrationTest.Passが実行されなければ失敗ということになっています。
ではどうするか。まず衝突判定用のCubeを2つ用意します。
縦に並ぶようにします。これらはNew Testの下につくようにします。
上のCubeにはRigitbodyをつけて、下のCubeはColiderのIs Triggerをチェック。
上のCubeが落ちてきて下のCubeに衝突したらOnTriggerEnterが動くようにします。
それで、上のCubeにスクリプトを追加して、OnTriggerEnterを追加します。
public void OnTriggerEnter() { IntegrationTest.Pass (gameObject); }
これでIntegration Test Runnerの「Run All」を実行すると、Cubeが衝突した瞬間テストが成功します。
Coroutineのテストをする
正直なところオブジェクトの衝突みたいなのは、実際使いどころがあまりわからないのでこっちが本命だと思ってる。
要はStartCoroutineが組み込まれている関数のテストですね。
NUnitはオブジェクトのメソッドをC#のみでテストしていたので、Unityが1フレームごとに呼び出す動作をする、StartCoroutineから始まるテストはできなかった。
メソッドの中のどこか一カ所でもStartCoroutineを使用しているとUnitTestでは上手く動かなくなってしまいます。
ですがこちらでは、MonoBehaviourがSceneで動作するのでそれができます。
Coroutineは意外と使ってるところがあって、例えばネットワーク接続とか。
wwwクラスを組み込んでいるメソッドはStartCoroutineを使ったりします。
なのでwwwクラスを使用したネットワークからデータを取得するテストを作ってみます。
まず、もうひとつCreateからテストを作り、こちらの名前は「CoroutineTest」にします。
その下にGameObjectを追加。それにスクリプトを追加。
そのスクリプトのStartを次のようにします。
IEnumerator Start () { string url = ""; // 任意のURL WWW www = new WWW (url); yield return www; Debug.Log (www.text); IntegrationTest.Pass (gameObject); }
urlには取得したい任意のサイトのURLを記入。
Integration Test RunnerよりCoroutineTestを選択して、「Run Selected」を実行すると、URLから取得したデータをコンソールに出力した後でテストが成功します。
本来なら取得結果を検証してからPassするべきなのですが、ひとまずそこは省略して。
このようにStartでのyield returnが使用できるため、StartCoroutineが使われたメソッドでもテストできるようになっています。
Updateも動いているので、毎フレームの実行が大事という場合も大丈夫。