Unity Test Framework で自作スクリプトをテストする(2)

前回は、UnityTest Framework パッケージにより作られたテスト用モジュール内のスクリプトから、自作スクリプトを参照できるようにするために、自作スクリプト群を自作モジュールに分け、そのアセンブリ定義ファイルの参照をテスト用モジュールのアセンブリ定義ファイルに追加しました。

unity のデフォルトのモジュール(自作スクリプトは既定ではここに入る) Assembly-CSharp.dll とアセンブリ定義ファイルで作成したモジュールは参照できる範囲が異なります。
Unity テスト用アセンブリ定義ファイルの設定でアセンブリ定義の参照リストの項目を1つ増やし自作モジュールを追加します。

これで自作スクリプトの名前空間や関数をテスト用モジュールのスクリプトから利用できるようになりました。
今回は、自作スクリプトのテストコードを作成して具体例として紹介します。
※ Unity は 2021.3.14f1、Test Framework パッケージは Version 1.1.33、Visual Studio は Community 版 Version 17.2.5、 OS は Windows 10 です。

テストコードの作成

テスト対象は自作スクリプトの SCTilemapExtensions.cs に定義された関数群です。
タイルマップに関する関数です。
そのため、テスト時には前回紹介したようにタイルマップのプレハブを用います。

テスト関数の名前は

では、英語を _ で区切っているようです。
英語は難しいので、「対象クラス名_対象メソッド名_通し番号」の形式で関数名をつけます。

SCGetTileCount 関数

Tilemap コンポーネントに配置されているマップチップの総数を得る関数です。

テストでは、マップチップの個数が 0 個のときに 0 を返すか、 3 個のときに 3 を返すか、確認します。

Tilemap コンポーネントを持つゲームオブジェクトプレハブとしてテスト用に用意しました。
※他の方法として、テスト関数の中で Tilemap を作成して、任意の個数だけマップチップを配置する方法もあると思いますが、複雑になるとテスト用の処理自体にバグが発生しやすくなると思い、前述の方法を選びました。

  • マップチップが 0 個配置されているタイルマップ
  • マップチップが 3 個配置されているタイルマップ
Unity Hierarchy ウィンドウからタイルマップを Project ウィンドウにドラッグ&ドロップしテスト用のタイルマップのプレハブを配置します。

タイルの作成については次のページにも書いてあります。

これらのテスト用プレハブテスト関数で読み込み、 Tilemap コンポーネントを対象の関数に渡し、戻り値が答えとあっているかを確認するコードを書きます。

using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.Tilemaps;
using SakuraCrowd.SCTilemap;

public class TestSCTilemapExtensions
{
    /// <summary>
    /// Resorces フォルダ内からプレハブを読み込み、それをインスタンス化し、Tilemap コンポーネントを得ます。
    /// </summary>
    /// <param name="tilemapPrefabPath">プレハブの Resources の後のパスです。</param>
    /// <param name="go">受け取るゲームオブジェクトです。 null の場合はログ出力と Assert が発生します。</param>
    /// <param name="tilemap">受け取る go の持つ Tilemap コンポーネントです。 null の場合はログ出力と Assert が発生します。</param>
    public void InstantiateTilmeapFromPrefab(string tilemapPrefabPath, out GameObject go, out Tilemap tilemap)
    {
        // プレハブを Resources フォルダ内から読み込みます。
        GameObject prefab = Resources.Load(tilemapPrefabPath) as GameObject;
        if (prefab == null)
        {
            Debug.Log("prefab is null. filepath = " + tilemapPrefabPath);
        }
        Assert.That(prefab, Is.Not.Null);

        // プレハブをインスタンス化します。
        go = GameObject.Instantiate(prefab);
        if (go == null)
        {
            Debug.Log("go is null");
        }
        Assert.That(go, Is.Not.Null);

        // Tilemap コンポーネントを取得します。
        tilemap = go.GetComponent<Tilemap>();
        if (tilemap == null)
        {
            Debug.Log("_wallsTilemap is null");
        }
        Assert.That(tilemap, Is.Not.Null);
    }

    /// <summary>
    /// SCTilemapExtensions の SCGetTileCount 関数のテストです。
    /// tilemapPrefabPath の Tilemap を SCGetTileCount 関数の結果と constraint が一致するか調べます。
    /// </summary>
    /// <param name="tilemapPrefabPath">テストに用いる Tilemap が含まれたプレハブの Resources の後のパスです。</param>
    /// <param name="constraint"></param>
    [TestCase("Test/Tilemap/TilemapCount0", 0)]
    [TestCase("Test/Tilemap/TilemapCount3", 3)]
    public void SCTilemapExtensions_SCGetTileCount_1(string tilemapPrefabPath, int constraint)
    {
        GameObject go;
        Tilemap tilemap;
        InstantiateTilmeapFromPrefab(tilemapPrefabPath, out go, out tilemap);

        int actual = tilemap.SCGetTileCount();
        Debug.Log("actual = " + actual + ", constraint = " + constraint);
        Assert.That(actual, Is.EqualTo(constraint));
    }
}

Test Runner から呼び出されるテスト用の関数は 52 行目の SCTilemapExtensions_SCGetTileCount_1 関数です。

関数の引数は、その前の 2 行の TestCase の引数と対応しています。
第 1 引数 tilemapPrefabPath はテストで用いる Tilemap を持つプレハブのパスです。
第 2 引数 constraint は、答えの数です。この場合は Tilemap に配置されたマップチップの個数です。

unity TestRunner ウィンドウでも TestCase 属性の引数が表示されます。

テスト関数で良く用いられる変数名に actual と answer/constraint があるようです。
テスト対象から得られた値は actual (実際の値)、答えは answer や constraint(制約、期待する状態) を用います。

テスト関数の処理は TestCase が 2 つあるので、それぞれの引数が渡されて 2 回このテスト関数は呼び出されます。

処理の内容は以下です。

  1. InstantiateTilmeapFromPrefab 関数でお題のタイルマップをプレハブからインスタンス化します。
  2. テスト対象の SCGetTileCount 関数を呼び出し、検証する値を取得します。
  3. 引数で渡された答えの値と一致するか Assert の中で確認します。もしも一致しなければテストは不合格になります。

メニュー [Window]→[General]→[Test Runner]Test Runner ウィンドウを表示し、2 つの TestCase または上位のテスト関数名ダブルクリックしてテストします。
テストが行われ、結果が表示されました。緑のチェックマークがつけば合格です。

Unity TestRunner でテスト用の関数をダブルクリックしてテストした結果

SetUp などの属性について

今回は使いませんでしたが、便利そうなテスト用の属性もたくさんあります。
その一部を紹介します。

SetUp 属性は、その関数をテスト関数が呼ばれる直前に毎回呼び出されるイベント関数にします。
毎回テストの最初に行う処理があれば SetUp 属性を指定した関数に実装すると良いでしょう。

OneTimeSetUp 属性は、その関数を最初のテストの直前に一度だけ呼び出されるイベント関数にします。
テストごとには行わない、初期化処理などを実装すると良いでしょう。

Values 属性は引数の前に指定し、その引数の値を複数指定できます。
TestCase で引数を渡す場合と似ていますが、複数の引数に Values を指定するとそのすべての組み合わせでテスト関数が呼び出されます。

【Unity】Unity Test Runner(Test Framework)で複数の入力値を取り扱う方法まとめ – LIGHT11

まとめ

今回は、Unity の Tilemap を利用する自作スクリプトの関数を Test Frameworkテストしました。
テスト用のタイルマップは、シーンで任意の数マップチップを配置したプレハブを用意しました。
テスト用の答えは、その Tilemap のプレハブのパスと対応させて TestCase 属性の引数で渡しました。

今回とは異なるテストの手順を使うことがあれば、今後も紹介していきたいです。

参照サイト Thank You!

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました