Unity 基础 之 简单介绍与使用 单元测试 Test Runner(NUnit) / Assert 基于 2019.3.x

Unity 基础 之 简单介绍与使用 单元测试 Test Runner / Assert 基于 2019.3.x 

 

目录

Unity 基础 之 简单介绍与使用 单元测试 Test Runner / Assert 基于 2019.3.x 

一、简单介绍

二、单元测试分为两个模式:Edit Mode 和 Play Mode

二、Assert 简单介绍

三、Edit Mode 单元测试的使用

注意:

简单使用步骤实现

关键代码

四、Play Mode 单元测试的使用

注意:

简单使用步骤实现

关键代码

五、Test Runer 面板简单说明

六、整理总结:

七、参考资料


 

一、简单介绍

Unity中的一些基础知识点。

本节简单介绍单元测试,并简单的进行一些使用,可能有疏漏,如果您有更好的方法,欢迎留言指正。

单元测试的可靠性

我们的目标是写出可靠、可维护、可读的测试。

因此,除了遵循单元测试结构规范编写单元测试之外,我们还需要注意可靠性、可维护性以及可读性这些方面。因此,一些原则我们也需要注意。

  • 不轻易删除和修改测试


一旦测试写好了并且通过了,就不应该轻易的修改和删除这些测试。因为这些测试是对应系统代码的保护伞,在修改系统代码时,这些测试会告诉我们修改后的代码是否会破坏已有的功能。

  • 尽量避免测试中的逻辑


随着测试中的逻辑增多,测试代码出现缺陷的几率也会增大。而且由于我们往往相信测试是可靠的,因此一旦测试出现缺陷我们往往不会首先考虑是测试的问题,可能会浪费时间去修改系统代码。而单元测试中,最好保持逻辑的简单,因此尽量避免使用下面的逻辑控制代码。

1.switch、if

2.foreach、for、while

一个单元测试应该是一系列的方法调用和断言,但是不应该包含控制流语句。

  • 只测试一个关注点


在一个单元测试中验证多个关注点会使得测试代码变得复杂,但却没有价值。相反,我们应该在分开的、独立的单元中验证多余的关注点,这样才能发现真正导致失败的地方。

 

单元测试的可维护性

  • 去除重复代码


和系统中的重复代码一样,在单元测试中重复代码同样意味着测试对象某方面改变时要修改更多的测试代码。

如果测试看上去都一样,仅仅是参数不同,那么我们完全可以使用参数化测试即使用[TestCase]特性将不同的数据作为参数传入测试方法。

  • 实施测试隔离


所谓的测试隔离,指的是一个测试和其他的测试隔离,甚至不知道其他测试的存在,而只在自己的小世界中运行。

将测试隔离的目的是防止测试之间的互相影响,常见的测试之间互相影响的情况可以总结如下:

1、强制的测试顺序:测试要以某种顺序执行,后一个测试需要前面的测试结果,这种情况有可能会导致问题的原因是因为NUnit不能保证测试按照某种特定的顺序执行,因此今天通过的测试,明天可能就不好用了

2、隐藏的测试调用:测试调用其他测试

3、共享状态被破坏:测试要共享状态,但是在一个测试完成之后没有重置状态,进而影响后面的测试

 

单元测试的可读性

正如概述中所说单元测试是一种无价的文档,它是展示方法或类如何使用的最佳文档。因此,可读性这条要求的重要性便可见一斑。试想一下即便是几个月之后别的程序员都可以通过单元测试来理解一个系统的组成以及使用方法,并能够很快的理解他们要做的工作以及在哪里切入。

  • 单元测试命名


在单元测试的结构中已经有过要求和介绍。参考那部分。

  • 单元测试中的变量命名


通过合理的命名变量,可以提高可读性,使得阅读测试的人员可以尽快的理解你要验证的内容。

 

二、单元测试分为两个模式:Edit Mode 和 Play Mode

官方网址介绍:https://docs.unity3d.com/2018.2/Documentation/Manual/testing-editortestsrunner.html

 

二、Assert 简单介绍

官方网址介绍:https://docs.unity3d.com/2019.3/Documentation/ScriptReference/Assertions.Assert.html

 

三、Edit Mode 单元测试的使用

官方网址介绍:https://docs.unity3d.com/2018.2/Documentation/Manual/testing-editortestsrunner.html

注意:

1)创建 Editor 文件夹,在 Editor 文件夹下即可创建 Testing 相关脚本

2)Edit Mode 可以引用自己其他文件夹下的脚本代码

3)可以不用创建 Tests Assembly Folder

4)UnityTest IEnumerator 测试中只能是 yield return null,其他或报错

 

简单使用步骤实现

1、创建一个 Editor 和 MyClass 文件夹,Editor  用于编写单元测试代码,MyClass  编写自己的代码脚本

 

2、MyClass  文件夹下新建一个脚本,编写简单代码,用于测试

 

3、选中 Editor 文件夹,右键新建 Create - Testing - C# Test Script

 

4、编写代码,测试 MyClass 函数,以及故意Assert 出错的案例

 

5、菜单Windows - General - Test Runner ,打开 Test Runner

 

6、点击 Run All 或者双击指定的测试用例也可以跑,结果如预期

 

关键代码

1)MyClass

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

namespace MyTestCalss { 

	public class MyClass 
	{

		public int Add(int a, int b) {
			return (a) + (b);
		}

		public int SubResult;
		public IEnumerator Sub(int a,int b) {
			yield return null;
			SubResult = (a) - (b);
		}


	}
}

 

2)EditModeTests

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

namespace Tests
{
    public class EditModeTests
    {
        private MyClass mMyClass;

        [SetUp]
        public void SetUp()
        {
            mMyClass = new MyClass();
        }

        // A Test behaves as an ordinary method
        [Test]
        public void EditModeTestsSimplePasses()
        {
            // Use the Assert class to test conditions

            int result = mMyClass.Add(1, 3);
            Debug.Log("Add(1,3) = " + result) ;
            Assert.AreEqual(result, 4);
        }

        // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
        // `yield return null;` to skip a frame.
        [UnityTest]
        public IEnumerator EditModeTestsWithEnumeratorPasses()
        {
            // Use the Assert class to test conditions.
            // Use yield to skip a frame.
            yield return null;

            yield return mMyClass.Sub(3,1);

            Debug.Log("Sub(3,1) = " + mMyClass.SubResult);

            Assert.AreEqual(mMyClass.SubResult, 2);
        }
    }

    public class EditModeTests2
    {
        

        // A Test behaves as an ordinary method
        [Test]
        public void EditModeTestsSimplePasses()
        {
            // Use the Assert class to test conditions
            Assert.IsFalse(true);
        }

        // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
        // `yield return null;` to skip a frame.
        [UnityTest]
        public IEnumerator EditModeTestsWithEnumeratorPasses()
        {
            // Use the Assert class to test conditions.
            // Use yield to skip a frame.
            yield return null;

            Assert.IsEmpty(null);
        }
    }
}

 

四、Play Mode 单元测试的使用

官方网址介绍:https://docs.unity3d.com/2018.2/Documentation/Manual/testing-editortestsrunner.html

注意:

1)可以在任意位置创建,但是建议新建一个脚本 PlayModeTests,便于管理

2)好似 Edit Mode 创建运行成功之后,才可不需要 Tests Assembly Folder 就可任意任意位置创建 PlayModeTests(有待进一步确定)

3)可以不用创建 Tests Assembly Folder

4)Tests Assembly Folder 创建以后,好似 引用不到该文件夹外的自定义脚本代码

5)特定Tests场景会自动运行与结束

6)Test Runners 窗口右侧的下拉菜单中选中 Enable play mode tests for all assemblies,注意在发布游戏前要把这个选项关掉,否则测试相关的内容也会被编译到最终文件中

 

简单使用步骤实现

1、创建一个文件夹PlayModeTests,并创建一个测试脚本

 

2、在 MyClass 文件夹 新建一个脚本,用于 Play Mode 模式下测试

 

3、编写 PlayModeTests 测试脚本,五个用例,一个 Ignore,一个不通过,三个通过

 

4、菜单Windows - General - Test Runner ,打开 Test Runner

 

5、点击 Run All 或者双击指定的测试用例也可以跑,结果如预期

 

关键代码

1)MyMonoClass

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

namespace Tests
{
    public class EditModeTests
    {
        private MyClass mMyClass;

        [SetUp]
        public void SetUp()
        {
            mMyClass = new MyClass();
        }

        // A Test behaves as an ordinary method
        [Test]
        public void EditModeTestsSimplePasses()
        {
            // Use the Assert class to test conditions

            int result = mMyClass.Add(1, 3);
            Debug.Log("Add(1,3) = " + result) ;
            Assert.AreEqual(result, 4);
        }

        // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
        // `yield return null;` to skip a frame.
        [UnityTest]
        public IEnumerator EditModeTestsWithEnumeratorPasses()
        {
            // Use the Assert class to test conditions.
            // Use yield to skip a frame.
            yield return null;

            yield return mMyClass.Sub(3,1);

            Debug.Log("Sub(3,1) = " + mMyClass.SubResult);

            Assert.AreEqual(mMyClass.SubResult, 2);
        }
    }

    public class EditModeTests2
    {
        

        // A Test behaves as an ordinary method
        [Test]
        public void EditModeTestsSimplePasses()
        {
            // Use the Assert class to test conditions
            Assert.IsFalse(true);
        }

        // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
        // `yield return null;` to skip a frame.
        [UnityTest]
        public IEnumerator EditModeTestsWithEnumeratorPasses()
        {
            // Use the Assert class to test conditions.
            // Use yield to skip a frame.
            yield return null;

            Assert.IsEmpty(null);
        }
    }
}

 

2)PlayModeTests

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

namespace Tests
{
    public class PlayModeTests
    {
        private MyMonoClass mMyMonoClass;

        [SetUp]
        public void SetUp()
        {
            mMyMonoClass = new GameObject("MyMonoClass").AddComponent<MyMonoClass>();
        }

        [Ignore("测试 Ignore")]
        public void PlayModeTestIgnore() {
            Assert.AreEqual(mMyMonoClass.mTestCounter, 0);
        }

        // A Test behaves as an ordinary method
        [Test]
        public void PlayModeTestsSimplePasses()
        {
            // Use the Assert class to test conditions
            int result = mMyMonoClass.mTestCounter;
            Debug.Log("mMyMonoClass.mTestCounter = " + result);
            Assert.AreNotEqual(result, 0);
        }

        // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
        // `yield return null;` to skip a frame.
        [UnityTest]
        public IEnumerator PlayModeTestsWithEnumeratorPasses()
        {
            // Use the Assert class to test conditions.
            // Use yield to skip a frame.
            yield return null;

            yield return mMyMonoClass.Test();

            Debug.Log("mMyMonoClass.mTestTime = " + mMyMonoClass.mTestTime);
            Debug.Log("mMyMonoClass.mTestCounter = " + mMyMonoClass.mTestCounter);
            Assert.AreEqual(mMyMonoClass.mTestTime, 3);
        }
    }

    public class PlayModeTests2
    {
        private MyClass mMyClass;

        [SetUp]
        public void SetUp()
        {
            mMyClass = new MyClass();
        }
        // A Test behaves as an ordinary method
        [Test]
        public void PlayModeTestsSimplePasses()
        {
            // Use the Assert class to test conditions
            int result = mMyClass.Add(1, 3);
            Debug.Log("Add(1,3) = " + result);
            Assert.AreEqual(result, 4);
        }

        // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
        // `yield return null;` to skip a frame.
        [UnityTest]
        public IEnumerator PlayModeTestsWithEnumeratorPasses()
        {
            // Use the Assert class to test conditions.
            // Use yield to skip a frame.
            yield return null;

            yield return mMyClass.Sub(3, 1);

            Debug.Log("Sub(3,1) = " + mMyClass.SubResult);

            Assert.AreEqual(mMyClass.SubResult, 2);
        }
    }
}

 

五、Test Runer 面板简单说明

Run All:测试全部用例

Run Selected:测试选中的用例

Rerun Failed: 重新测试上一次未通过的测试用例

搜索框:可以搜索用例

种类过滤器:可以根据种类来筛选用例。种类需要在测试代码中使用CategoryAttribute来标识

测试结果筛选器:可以按照通过、失败以及忽略来筛选用例

PlayMode / EditMode  :Play 模式和 Edit 模式面板切换

 

六、整理总结:

1、Edit Mode 测试应该放在 Editor 目录或其子目录下。

2、Play Mode 测试放在非 Editor 目录下,建议放 Assets/PlayModeTests,并需要在 Test Runners 窗口右侧的下拉菜单中选中 Enable play mode tests for all assemblies。注意在发布游戏前要把这个选项关掉,否则测试相关的内容也会被编译到最终文件中。

3、测试函数要标上 [Test] 或者 [UnityTest] 属性才会被 Test Runner 识别,前者是普通测试,后者具有跳过帧的能力(可使用 yield return null,根据测试模式决定是跳 EditorApplication.update 还是 update)。

4、[UnityTest] 在 Edit Mode 中是跳过 EditorApplication.update, 在 PlayMode 中是跳过 Monobehavior 的 Update。要测试涉及到游戏内 Update 相关内容时,必须将测试写为 PlayMode 测试; Edit Mode 的测试只用于与 Update 无关或者与 Editor 的 Update 相关的内容(主要是编辑器插件关注)。

5、    总结:显式或涉及 Update 的测试内容全部需要放在 Play Mode 下,其他的在 Edit Mode 下。

6、Play Mode 测试运行时会新建临时场景,运行后自动删除,而 Edit Mode 则不会。

7、使用 Assert 类语法对关注的值进行测试,具体可用内容参见 NUnit 文档。

参考网址:https://github.com/nunit/docs/wiki/NUnit-Documentation

 

七、参考资料

参考博文:https://blog.csdn.net/jinxiul5/article/details/82114407

Unity Test Runner 官方手册:https://docs.unity3d.com/Manual/testing-editortestsrunner.html

https://docs.unity3d.com/Manual/testing-editortestsrunner.html

https://docs.unity3d.com/Manual/PlaymodeTestFramework.html

使用NUnit为Unity3D编写高质量单元测试的思考:https://www.gameres.com/668571.html

TDD在Unity3D游戏项目开发中的实践:https://www.gameres.com/497930.html

Unity 单元测试(NUnit,UnityTestTools):https://www.cnblogs.com/plateFace/p/5176961.html

在Unity中写单元测试:https://blog.csdn.net/kingsea168/article/details/49583083

 

  • 15
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
本书对Unity 3D集成开发环境界面、脚本的编写和众多高级特效的实现进行了详细介绍,内容深入浅出,是一本适合不同需求、不同开发水平读者的技术宝典。 全书共分16章。第1章主要介绍Unity 3D的诞生、特点、开发环境的搭建及运行机制;第2章对Unity 3D集成开发环境进行了详细介绍;第3章介绍Unity 3D中脚本的编写;第4章主要对Unity 3D开发过程中经常使用的组件及对象进行了详细介绍;第5章介绍Unity游戏开发中非常流行的第三方UI界面开发组件库—NGUI的基础知识;第6章介绍Unity开发平台的完整的物理引擎体系;第7章介绍Unity 3D中的着色器和着色器语言—ShaderLab;第8章介绍了天空盒、虚拟按钮与摇杆、声音、水特效、3D拾取、重力加速度传感器及雾特效等开发常用的技术;第9章介绍Unity中经常使用的光影效果,主要包括各种光源、光照烘焙、法线贴图、镜面特效、波动水面真实效果等技术;第10章介绍Unity中模型的网格概念及新旧动画系统;第11章介绍Unity自带的地形引擎、拖尾渲染及导航网格和寻路系统等知识;第12章介绍了AssetBundle更新资源包的使用;第13章介绍Unity中的多线程技术与网络开发;第14章介绍Unity 2D游戏开发工具;第15章介绍Unity 3D提供的Profiler工具的使用方法,及断点调试的两种方式;第16章介绍了完整的大型3D游戏案例—指间足球。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙魁XAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值