TDD与Unity3D游戏开发
0x00 前言关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音。那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使用U3D 5.3.X之后版本已经集成的单元测试模块Editor Test Runner。 0x01 你好,TDDTDD,测试驱动开发改变了我们常见的工作流程,不要求先写逻辑代码,反而要求先完成测试代码。待测试代码完成之后,我们再将目光转移到逻辑代码,根据测试的要求,完成逻辑代码,使之能够通过经过拆分后粒度已经很小的测试。这样做有什么好处呢?
0x02 流程,驱动为了进行TDD测试驱动开发,我们需要了解TDD的流程或者说技巧,大体上可以将其步骤简单的归纳为:<font color=red>红灯</font>-><font color=green>绿灯</font>->重构。 红灯下面,我们就利用NUnit来编写我们的第一个测试,来看看测试是如何驱动开发的: //测试被攻击之后伤害数值是否和预期值相等 [Test] public void TakeDamage_BeAttacked_HpEqual() { HpComp health = new HpComp(); health.currentHp = 100; health.TakeDamage(50); Assert.AreEqual(50f,health.currentHp); } 首先可以看到测试代码的方法名很长,而且测试名中还包括下划线来保证我们不会漏掉关于这个测试的重要信息(被测试的方法_测试进行的条件_预期结果),因为在编写测试代码时,可读性是重要的考量之一。 绿灯测试写完了,此时是红灯,而此时将这个红灯变成绿灯的要求,便驱使着我们进行开发。所幸的是,我们要开发的内容,已经在测试中体现了出来:
只要满足这3点,我们就可以很轻易的使红灯变成绿灯。所以,为了满足测试条件,我们可以十分简单粗暴的写出如下的代码: public class HpComp { public float currentHp; public void TakeDamage(float damage) { this.currentHp = 50f; } } 好了,在上面的测试代码中只要调用TakeDamage方法,currentHp的值便被设置为了50,和断言中的预期符合,因此测试通过,状态也由<font color=red>红灯</font>变成了<font color=green>绿灯</font>。当然,我们简单的实现就通过了第一个测试,此时如果有优化代码的需求,我们就需要对代码进行重构,使得代码更加干净。 再来几次我们的第一个测试用例驱动开发出的代码显然满足了第一个测试的需求,但是如果我们重新回到原点,并且思考一下除了满足第一个测试中提供的数据,我们的代码还能做什么,如果换一个测试条件结果会变得怎样呢? //测试被攻击之后伤害数值是否和预期值相等 [Test] public void TakeDamage_BeAttacked_HpEqual2() { HpComp health = new HpComp(); health.currentHp = 150; health.TakeDamage(10); Assert.AreEqual(140f,health.currentHp); } 这是一个新的测试(暂时叫做测试2),这就意味着TakeDamage方法除了通过第一个测试之外,还必须通过这个新的测试2。此时,我们最初的TakeDamage的实现,显然无法通过测试2,因此测试2是<font color=red>红灯</font>状态。 public void TakeDamage(float damage) { this.currentHp -= damage; } 这样,它不仅通过了测试1,同时也通过了测试2。 TDD流程小结通过上面的小例子,我们可以看到TDD的流程或者说开发技巧并不难理解:
0x03 问题,方案由于游戏开发和传统软件开发之间的差异,因此在开发游戏的过程中编写单元测试,会面临两个主要的问题: 针对问题1,由于对I/O处理以及UI视觉方面的操作比较难以实施单元测试,所以我们单元测试的主要对象是逻辑操作以及数据存取的部分。 0x04 实践,U3D中的单元测试在Untiy编辑器中写单元测试:编写单元测试用例时,使用的主要是Unity Editor自带的单元测试模块,因此单元测试是基于NUnit框架的。 using UnityEngine; using System.Collections; using NUnit.Framework; [TestFixture] public class HpCompTests { //测试被攻击之后伤害数值是否和预期值相等 [Test] public void TakeDamage_BeAttacked_HpEqual() { HpComp health = new HpComp(); health.currentHp = 100; health.TakeDamage(50); Assert.AreEqual(50f,health.currentHp); } } 完成之后,我们就可以打开Unity 5.3.x中集成的单元测试模块来进行自动化测试了。 好了,本文到此就暂时打住了,之后有新的体验和想法,还会继续这个话题的总结,也欢迎各位讨论。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |