使用协程设置进行PlayMode测试

时间:2019-10-19 19:21:15

标签: c# unit-testing unity3d nunit

我是Unity3D测试的新手,我想为我们的游戏编写一些测试。我设法编写了此测试,该测试

using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Game.Characters;
using Game.Inventory;

namespace Tests
{
    public class ItemTests
    {
        [UnityTest]
        public IEnumerator ItemIsOnHand()
        {
            // Setup
            Player player = MonoBehaviour.Instantiate(Resources.Load<GameObject>("Tests/Player"));
            yield return null; // Wait for prefab to load
            Character character = player.GetComponent<Character>();
            WorldItem worldItem = WorldItem.Create(Resources.Load<Item>("Items/item"), 1);
            yield return null; // Wait for prefab to load
            character.Inventory.Give(worldItem);
            ItemScript itemScript = character.HandItemContainer.gameObject.GetComponentInChildren<ItemScript>();

            // Test
            Assert.IsNotNull(itemScript);

            // Teardown
            Object.Destroy(player);
            Object.Destroy(character);
            Object.Destroy(worldItem);
            Object.Destroy(itemScript);
        }

        [UnityTest]
        public IEnumerator ItemIsDisabledAtStart()
        {
            // Setup
            Player player = MonoBehaviour.Instantiate(Resources.Load<GameObject>("Tests/Player"));
            yield return null; // Wait for prefab to load
            Character character = player.GetComponent<Character>();
            WorldItem worldItem = WorldItem.Create(Resources.Load<Item>("Items/item"), 1);
            yield return null; // Wait for prefab to load
            character.Inventory.Give(worldItem);
            ItemScript itemScript = character.HandItemContainer.gameObject.GetComponentInChildren<ItemScript>();

            // Test
            Assert.IsFalse(itemScript.IsActive);

            // Teardown
            Object.Destroy(player);
            Object.Destroy(character);
            Object.Destroy(worldItem);
            Object.Destroy(itemScript); 
        }
    }
}

如您所见,两个测试(以及其他测试)都使用相同的设置和拆卸。我在方法之外声明变量(可用于每个测试)。拆卸方法可以正常工作,因为它不需要等待任何加载。

        private Player player;
        private Character character;
        private WorldItem worldItem;
        private ItemScript itemScript;

        [TearDown]
        public void Teardown()
        {
            Debug.Log("Teardown called");
            Object.Destroy(player);
            Object.Destroy(character);
            Object.Destroy(ectomodulatorWorldItem);
        }

但是我无法使SetUp方法正常工作。如果我将其作为协程([SetUp] public IEnumerator SetUp(){...}),它将永远不会运行(我已通过调试器进行检查)。而且,如果我将其设为简单的void方法并删除yield return null,则它会在character.Inventory.Give(worldItem);失败,因为worldItem仍然是null

有什么办法可以使SetUp方法工作?

谢谢

1 个答案:

答案 0 :(得分:0)

我找到了我所需要的。就像[Test]属性仅适用于void方法,并且您需要使用[UnityTest]来运行协程一样,还有一个[UnitySetUp]属性允许使用协程设置而不是一个void

链接至文档以获取更多信息:https://docs.unity3d.com/Packages/com.unity.test-framework@1.1/manual/reference-actions-outside-tests.html#unitysetup-and-unityteardown

如果您有兴趣,我的测试文件如下:

using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Game.Characters;
using Game.Inventory;

namespace Tests
{
    public class ItemTests
    {
        Player player;
        Character character;
        WorldItem worldItem;
        ItemScript itemScript;

        [UnitySetUp]
        public IEnumerator SetUp()
        {
            player = MonoBehaviour.Instantiate(Resources.Load<GameObject>("Tests/Player"));
            yield return null; // Wait for prefab to load
            character = player.GetComponent<Character>();
            worldItem = WorldItem.Create(Resources.Load<Item>("Items/item"), 1);
            yield return null; // Wait for prefab to load
            character.Inventory.Give(worldItem);
            itemScript = character.HandItemContainer.gameObject.GetComponentInChildren<ItemScript>();
        }

        [TearDown]
        public void Teardown()
        {
            Object.Destroy(player);
            Object.Destroy(character);
            Object.Destroy(ectomodulatorWorldItem);
        }

        [Test]
        public void ItemIsOnHand()
        {
            // Test
            Assert.IsNotNull(itemScript);
        }

        [Test]
        public void ItemIsDisabledAtStart()
        {
            // Test
            Assert.IsFalse(itemScript.IsActive);
        }
    }
}