興味の源泉

自分が興味を起こせるようなネタを雑多に書き綴るブログ

Unityでテスト【TestRunner】

f:id:nanami_yamato:20190322015626p:plain

最近テスト駆動開発の翻訳をした和田卓人さんの話を聴く機会があって、テストの重要性を改めて気づき手法について考えていました。
そういやUnityのテストをしやすくするツールあったなと思いだしたので触ってみようかと思います。


UnityにはTestRunnerというツールが標準でついています。
呼び出すのには メニューのWindow > General > TestRunner でダイアログが開きます。
f:id:nanami_yamato:20190321225634p:plain

PlayMode

PlayModeはどのソースコードに対してもテストできます。
コルーチンとして実行します。
実行速度がEditModeに比べて遅いです。
実際に画面を動かしてテストしたい場合などはこちらのモードになります。

EditMode

EditModeはMonoBehaviourを継承しないソースコードをテストするのに最適のモードです。
実行速度がPlayModeに比べ速いです。
例えば計算を行ったり情報の保持しているクラスなどをテストするのに使うと良いかと思います。


今回はEditModeで作ります。

まずAssets以下にEditorフォルダがない場合は作成します。
ProjectウィンドウでEditorフォルダに移動し、Testsフォルダを作ってその中にテストファイルを作っていきます。
Editorフォルダに作るのは通常のビルド時に含めたくないからです。

テスト用のソースファイルを作ります。
テストのフォルダで右クリック > Create > Testing > C# Test Scriptで作ります。
EditModeTestScript1という名前で作りました。

EditModeTestScript1AddTestというテスト関数を作ります。
EditModeの場合、引数無しの戻り値の型はvoidです。
ついでにエラー時の挙動も見たいのでEditModeTestScript1ErrorTestというテスト関数を作りました。

using NUnit.Framework;
using UnityEngine;

namespace Tests
{
    public class EditModeTestScript1
    {
        [Test]
        public void EditModeTestScript1AddTest()
        {
            int a = 1;
            int b = 3;
            Debug.Log(a + b);
        }

        [Test]
        public void EditModeTestScript1ErrorTest()
        {
            UnityEngine.Assertions.Assert.IsTrue(false, "ErrorTest");
        }
    }
}

TestRunnerの左上の「Run All」を押してすべてを実行します。
テストを選びたい場合は「Run Selected」を押して実行します。
各関数の名前をクリックすると結果が表示されます。
f:id:nanami_yamato:20190322015138p:plain

エラーを取り除きたいので、EditModeTestScript1ErrorTest関数をAssertを吐かないように修正します。

    UnityEngine.Assertions.Assert.IsTrue(true, "ErrorTest");

これで実行結果はオールグリーンになりました。
f:id:nanami_yamato:20190322015457p:plain


ファイルを分けて作ることも可能です。
EditModeTestScript2ファイルを追加し、AddTestテスト関数を追加しました。

using NUnit.Framework;
using UnityEngine;

namespace Tests
{
    public class EditModeTestScript2
    {
        [Test]
        public void AddTest()
        {
            int a = 5;
            int b = 9;
            Debug.Log(a + b);
        }
    }
}


次にテストフォルダ以外にあるソースをテストします。
StringTestScriptという文字列を扱う以下のクラスをテストします。
Editorフォルダ以外の任意の場所に下記ソースを書いたファイルを作ります。

public class StringTestScript
{
    public StringTestScript(string str)
    {
        CurrentString = str;
    }

    public string CurrentString { get; private set; }

    public void AddString(string addStr)
    {
        CurrentString += addStr;
    }
}

EditModeTestScript2にStringAddTestというテスト関数を追加します。

        [Test]
        public void StringAddTest()
        {
            StringTestScript sts = new StringTestScript("aaa");

            // CurrentStringに設定してある文字列を表示
            Debug.Log("before:" + sts.CurrentString);

            // bbb文字列を追加
            sts.AddString(" bbb");

            // CurrentStringに設定してある文字列を表示
            Debug.Log("after:" + sts.CurrentString);
        }


実行結果は

before:aaa
after:aaa bbb

のようにでます。
f:id:nanami_yamato:20190322015626p:plain


今回はTestRunnerのEditModeを使ってテストを書いてみました。
仕事では必要に駆られればテストコードも書きますが、もっと積極的に書いていく習慣をつけていかなければなーと改めて思いました。

動いているコードが触れない理由の一つに変更した前後で動きが変わっていないか保証できないというものがあります。
テストコードがあればそこをカバーしていける部分も出てきて、過去の負債を抱えてずっとやっていくみたいなことを変えていけるかもしれませんね。