Open7

Unity Test Runnerの使い方

brainvaderbrainvader

よくわからないままUnityのテスト・コードを書いてみた. SetUpとTearDownはいらなかった気がする. GameObject.Destroy()だとDestroyImmediateを使えって怒られた.

using NUnit.Framework;
using UnityEngine;
using TMPro;

public class MaxThreeNumbersTest {
    private GameObject element1, element2, element3;

    [SetUp]
    public void SetUp() {
        element1 = new GameObject("Element0");
        element1.AddComponent<TextMeshPro>();
        element1.GetComponent<TextMeshPro>().text = "1";
        element2 = new GameObject("Element1");
        element2.AddComponent<TextMeshPro>();
        element2.GetComponent<TextMeshPro>().text = "15";
        element3 = new GameObject("Element2");
        element3.AddComponent<TextMeshPro>();
        element3.GetComponent<TextMeshPro>().text = "9";
    }

    [Test]
    public void ReturnMaxOfThreeNumbers() {
        var values = new int[] {
            int.Parse(element1.GetComponent<TextMeshPro>().text),
            int.Parse(element2.GetComponent<TextMeshPro>().text),
            int.Parse(element3.GetComponent<TextMeshPro>().text)
        };

        var maxIndex = MaxThreeNumbers.Max(values);
        var got = values[maxIndex];
        var expected = 15;

        Assert.AreEqual(got, expected);
    }

    [TearDown]
    public void TearDown() {
        GameObject.DestroyImmediate(element1);
        GameObject.DestroyImmediate(element2);
        GameObject.DestroyImmediate(element3);
    }
}

MaxThreeNumbersTest.cs

murnanamurnana

GameObject.Destroy()だとDestroyImmediateを使えって怒られた

GameObject.Destroy() はPlayModeでしか使用できません。そのため、EditModeでテストを行う場合は GameObject.DestroyImmediate() を使用する必要があります。

brainvaderbrainvader

TestCaseSourceのパラメータが渡せない

テストケースとしてランダムな数値列を生成するのにTestCaseSourceを使ってみたが, 引数の渡し方がよくわからない. いろいろよくわからないので供養しておく.

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


public class ReverseArrayTest {
    const int MAX = 100;
    const int ARRAY_SIZE = 5;

    [Test]
    [TestCaseSource(nameof(RandomArrays), new int[] { 10, 7, 12 })]
    public void ReverseArrayOrder(int[] arr) {
        int firstElement = arr[0];
        // int lastElement = arr[ARRAY_SIZE - 1];
        // int middleElement = arr[ARRAY_SIZE / 2];

        int[] rev_arr = ReverseArray.Reverse(arr);
        Assert.That(firstElement, Is.EqualTo(rev_arr[ARRAY_SIZE - 1]));
        // Assert.That(lastElement, Is.EqualTo(rev_arr[0]));
        // Assert.That(middleElement, Is.EqualTo(rev_arr[ARRAY_SIZE / 2]));
    }

    static IEnumerable<int[]> RandomArrays(int[] array_sizes) {
        yield return GenRandomArray(array_sizes[0]);
        yield return GenRandomArray(array_sizes[1]);
        yield return GenRandomArray(array_sizes[2]);
    }

    static int[] GenRandomArray(int array_size = ARRAY_SIZE) {
        int[] randomArray = new int[array_size];
        var rnd = new System.Random();
        for (int i = 0; i < array_size; i++) {
            randomArray[i] = rnd.Next(MAX);
        }
        return randomArray;
    }
}
murnanamurnana

大分経過していますが、なんとなく気になったので書いてみました。
TestCaseSourceAttributeですが、これは入力 (引数)を TestCaseDataとして格納する必要があります。
また今回はvoidなので書いていませんが、TestCaseDataは、テスト関数を実行した際の正しい戻り値も指定できます。

一方で、テスト関数の引数に値を指定できる ValueSourceAttributeというのもあります。
もし複数の引数があり、その組み合わせによるテストが欲しい場合に活用できますよ。

using System;
using System.Collections.Generic;

using NUnit.Framework;



public class ReverseArrayTest {
    private const int MAX        = 100;
    private const int ARRAY_SIZE = 5;

    private static IEnumerable<int[]> RandomArray {
        get {
            foreach (int array_size in new[] { 10, 7, 12 }) {
                yield return GenRandomArray(array_size);
            }
        }
    }

    private static IEnumerable<TestCaseData> RandomArrayTestCaseDatas {
        get {
            foreach (int array_size in new[] { 10, 7, 12 }) {
                yield return new TestCaseData(GenRandomArray(array_size));
            }
        }
    }

    /// <summary>
    /// <see cref="ValueSourceAttribute" />を使用した、引数にテストケースとなる値を入れるサンプルです
    /// </summary>
    /// <param name="arr"></param>
    [Test]
    public void ReverseArrayOrder_FromParams([ValueSource(nameof(RandomArray))] int[] arr) {
        int firstElement = arr[0];
        // int lastElement = arr[ARRAY_SIZE - 1];
        // int middleElement = arr[ARRAY_SIZE / 2];

        int[] rev_arr = ReverseArray.Reverse(arr);
        Assert.That(firstElement, Is.EqualTo(rev_arr[ARRAY_SIZE - 1]));
        // Assert.That(lastElement, Is.EqualTo(rev_arr[0]));
        // Assert.That(middleElement, Is.EqualTo(rev_arr[ARRAY_SIZE / 2]));
    }

    /// <summary>
    /// <see cref="TestCaseSourceAttribute" /> を使用した、テストケース生成のサンプルです
    /// </summary>
    /// <param name="arr"></param>
    [Test]
    [TestCaseSource(nameof(RandomArrayTestCaseDatas))]
    public void ReverseArrayOrder_FromTestCase(int[] arr) {
        int firstElement = arr[0];
        // int lastElement = arr[ARRAY_SIZE - 1];
        // int middleElement = arr[ARRAY_SIZE / 2];

        int[] rev_arr = ReverseArray.Reverse(arr);
        Assert.That(firstElement, Is.EqualTo(rev_arr[ARRAY_SIZE - 1]));
        // Assert.That(lastElement, Is.EqualTo(rev_arr[0]));
        // Assert.That(middleElement, Is.EqualTo(rev_arr[ARRAY_SIZE / 2]));
    }

    /// <summary>
    /// ランダムな配列を生成します
    /// </summary>
    /// <param name="array_size"></param>
    /// <returns></returns>
    private static int[] GenRandomArray(int array_size = ARRAY_SIZE) {
        int[]  randomArray = new int[array_size];
        Random rnd         = new Random();
        for (int i = 0; i < array_size; i++) {
            randomArray[i] = rnd.Next(MAX);
        }

        return randomArray;
    }
}