MRが楽しい

MRやVRについて学習したことを書き残す

Unity Test FrameworkのEdit Modeを使って関数の単体テストを作成して実行する

本日は Unity の技術調査枠です。
UnityTestFramework の EditMode を使って関数の単体テストを作成して実行する手順を記事にします。
f:id:bluebirdofoz:20210805214326j:plain

UnityTestFramework

UnityTestFramework はコードの自動テストを行うためのツールです。
自動テストを使用すると、コードが期待どおりに機能していることを簡単に確認できます。
docs.unity3d.com

テストには EditMode と PlayMode の2つのモードがあります。
本記事では EditMode を用いて、自作スクリプト単体テストを作成して実行してみます。

サンプルプロジェクト

試験を行う Unity プロジェクトを作成します。
f:id:bluebirdofoz:20210805214344j:plain

試験対象のスクリプトとして、以下の簡単な計算関数を持ったスクリプトを作成しました。
・SampleClass.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleClass
{
    /// <summary>
    /// 足し算
    /// </summary>
    public int Add(int a_Alpha, int a_Beta)
    {
        return a_Alpha + a_Beta;
    }

    /// <summary>
    /// 引き算
    /// </summary>
    public int Sub(int a_Alpha, int a_Beta)
    {
        return a_Alpha - a_Beta;
    }

    /// <summary>
    /// 掛け算
    /// </summary>
    public int Multi(int a_Alpha, int a_Beta)
    {
        return a_Alpha * a_Beta;
    }
}

f:id:bluebirdofoz:20210805214355j:plain

EditModeのテストを作成する

初めに EditMode で動作するテストスクリプトを作成して実行してみます。

テストスクリプトの作成

メニューから[Window -> General -> TestRunner]を開きます。
f:id:bluebirdofoz:20210805214404j:plain

[Test Runner]ダイアログが開きます。
選択中のフォルダにテストが未作成の状態だと[Create]ボタンが表示されます。
f:id:bluebirdofoz:20210805214413j:plain

[EditMode]タブを開き、[Create Edit Mode Test Assembly Folder]ボタンをクリックします。
すると、選択中のフォルダに TestAssembly を含むフォルダが生成されます。
f:id:bluebirdofoz:20210805214422j:plain

そのまま、作成したフォルダを選択した状態だと[Create Test Script in current folder]ボタンが表示されます。
ボタンをクリックすると、テストスクリプトが作成されます。
f:id:bluebirdofoz:20210805214433j:plain

これで[Test Runner]ダイアログに現在作成中のテストスクリプトが追加されます。
f:id:bluebirdofoz:20210805214443j:plain

テストスクリプトを編集して必ず成功するテストコードを書いてみます。
Assert.That メソッドを使って、テストしたい条件式を記述します。
docs.microsoft.com
・TestEditModeScript.cs

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

public class TestEditModeScript
{
    // テスト
    [Test]
    public void TestEditModeScriptSimplePasses()
    {
        // 必ず成功を返す
        Assert.That(true);
    }
}

f:id:bluebirdofoz:20210805214503j:plain

この状態でテストを実行してみます。
テストを実行するには[Test Runner]ダイアログの[Run All]をクリックします。
f:id:bluebirdofoz:20210805214513j:plain

テストが実行され、成功すると以下の通り、緑色のチェックマークが表示されます。
f:id:bluebirdofoz:20210805214523j:plain

試験の条件式が false を返す(失敗した)場合は以下の通り、赤色のチェックマークが表示されます。

// 必ず失敗を返す
Assert.That(false);

f:id:bluebirdofoz:20210805214534j:plain

プロジェクトのスクリプトを参照する

次に先ほど作成したサンプルスクリプトをテストしてみます。

デフォルト時の参照エラー

以下のようにスクリプトを参照してテストするコードを書いてみます。

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

public class TestEditModeScript
{
    // 足し算テスト
    [Test]
    public void TestEditModeScriptSimplePasses_Add()
    {
        SampleClass testIns = new SampleClass();
        Assert.That(testIns.Add(1, 2), Is.EqualTo(3));
    }

    // 引き算テスト
    [Test]
    public void TestEditModeScriptSimplePasses_Sub()
    {
        SampleClass testIns = new SampleClass();
        Assert.That(testIns.Sub(1, 2), Is.EqualTo(-1));
    }

    // 掛け算テスト
    [Test]
    public void TestEditModeScriptSimplePasses_Multi()
    {
        SampleClass testIns = new SampleClass();
        Assert.That(testIns.Multi(1, 2), Is.EqualTo(2));
    }
}

f:id:bluebirdofoz:20210805214548j:plain

すると以下のようにスクリプトへの参照エラーが発生します。

The type or namespace name 'SampleClass' could not be found.

f:id:bluebirdofoz:20210805214559j:plain

これはテストスクリプトが Assembly definitions の機能により、アセンブリが分割されているためです。
参照エラーを解決するには、テスト対象のスクリプトにも Assembly definitions を適用してその参照を追加する必要があります。

Assembly definitionsの作成

Assembly definitions を作成したフォルダ配下がアセンブリで分割されます。
ここでは分かりやすく Assets フォルダ直下に Assembly definitions を作成し、テスト対象のスクリプトを含むアセンブリを作成します。
docs.unity3d.com

右クリックから[Create -> Assembly Definition]を実行します。
f:id:bluebirdofoz:20210805214611j:plain

これでテスト対象のスクリプトを含むアセンブリが作成できました。
f:id:bluebirdofoz:20210805214622j:plain

Tips

何故、アセンブリへの参照を追加するためにアセンブリ分割を行わないといけないかについてです。
Assembly definitions を設定していないスクリプトは全て Assembly-CSharp のアセンブリに含められます。
docs.unity3d.com

この Assembly-CSharp は扱いが特殊であり、他のアセンブリから Assembly-CSharp への参照はできません。
このため、テスト対象のスクリプトを含むアセンブリを参照するには、そのスクリプトに Assembly definitions を設定して Assembly-CSharp とは異なるアセンブリに分割しておく必要があります。

テスト対象への参照を追加

テスト対象のアセンブリを作成したら、テストスクリプトアセンブリを開きます。
[Assembly Definition References]の項目に参照を追加するため、[+]ボタンをクリックします。
f:id:bluebirdofoz:20210805214656j:plain

先ほど作成したアセンブリの参照を選択して追加します。
f:id:bluebirdofoz:20210805214706j:plain

[Apply]ボタンをクリックして変更を反映します。
f:id:bluebirdofoz:20210805214718j:plain

これでテスト対象のスクリプトを参照できるようになり、エラーが解消されました。
f:id:bluebirdofoz:20210805214729j:plain

テストの実行

再び[Test Runnder]ダイアログを開き、[Run All]でテストを実行してみます。
f:id:bluebirdofoz:20210805214740j:plain

全てのテストが実行され、テスト対象の関数が正常な値を返すことが確認できました。
f:id:bluebirdofoz:20210805214749j:plain

Play Modeの利用手順

Play Modeの利用手順については以下の記事を参照ください。
bluebirdofoz.hatenablog.com