






















3.4 XNA 中的单元测试
在进一步学习辅助类之前,本节先来简单地讨论一下单元测试。上一章您已经学习了静态单元测试(static unit test),静态单元测试非常适用于快速检测输出结果、测试物理特性和控制器以及快速构建游戏。但是辅助类和组件不需要用户输入,这就要求您自己来处理它们。这是没有意义的,因为单元测试主要是为了改进应用程序的可维护性,并确保尽可能少地出现错误。例如,可以使用下面的代码来测试Log类是否可以工作:
FileHelper.DeleteFile(Log.LogFilename);
Log.Write("New log entry");
提示:这段代码只能在Log类内部执行,因为Log.LogFilename是私有的。 现在,您可以查看一下应用程序的目录中是否有日志文件,并且其中包含“New log entry”信息。不过,自己反反复复地检查文件内容是很麻烦的。不要把所有错误信息都记录下来,您只需记录下不是特别重要的警告信息(比如用户没有连接到Internet),而对于严重的错误要抛出异常(比如找不到texture,shader不可用等等)。当问题变得越来越多,测试变得更加复杂并且需要漫长的检测过程,尤其应当这么做。您可以用单元测试来进行错误检测,这样就不用亲自去做了,也可以让它们自动地被执行,而不是像使用静态单元测试要亲自从Program类中去调用。
NUnit和TestDriven.Net
要达到上述目的您可以使用流行的NUnit Framework,可以在这里下载:http://www.nunit.org 。 另外,如果您使用的是Visual Studio 2005 Professional或更高版本,也可以使用TestDrive.Net,可以从http://www.testdriven.net 得到。它支持很多非常好的特性,直接使用热键和弹出菜单就可以进行测试,非常简单。VC# Express和XNA Studio Express不支持TestDriven.Net(一年前倒是支持的,但由于Microsoft希望开发者使用Professional版本,所以Express版本就不再支持这个插件)。关于在Visual Studio 2005中如何使用XNA可以参见第一章的相关内容,可以在XNA Studio Express中使用一个临时项目来处理内容素材,因为在Visual Studio 2005中不支持。 不管安装哪个版本,只要把动态库NUnit.Framework.dll添加到项目中就可以了(右键单击项目添加一个新的引用,在打开的窗口中第一个标签页显示的是全局程序集缓存——Global Assembly Cache,如果这里找不到NUnit.Framework.dll,可以切换到“浏览”标签页定位到NUnit的安装目录中找到它)。现在您可以添加下面的指令:
#if DEBUG
using NUnit.Framework;
#endif
我通常把这段代码放在using指令区域的顶部,而且它之所以只在调试模式下使用,是因为只有在调式模式下才会使用单元测试,对于最终发布的游戏您也不想要这些额外的NUnit.Framework.dll和所有的测试代码,因为游戏不需要这些。 作为一个例子,您可以看看StringHelper类中使用的第一个单元测试,它主要检测IsInList方法是否按预期工作:
[TestFixture]
public class StringHelperTests
{
/// <summary>
/// Test IsInList
/// </summary>
[Test]
public void TestIsInList()
{
Assert.IsTrue(IsInList("whats",
new string[] { "hi", "whats", "up?" }, false));
Assert.IsFalse(IsInList("no way",
new string[] { "omg", "no no", "there is no way!" }, false));
} // TestIsInList()
…
其中Assert是NUnit框架中的一个辅助类,它包含一些检查返回值是否正确的方法。如果返回值不正确,就会抛出一个异常,您可以立即看到是哪行出了错。例如上述代码中,Assert.IsTrue检查IsInList方法的返回值是否是true,如果是false,就抛出一个异常。其中第一个测试的字符串数组中包含了字符串“whats”,返回值就是true,那么这个测试就通过了。第二个测试是否存在“no way”,而字符串数组中没有,那么返回值就是false。请注意:虽然“there is no way!”中包含了“no way”,但此处测试的不是Contains方法(虽然StringHelper类中的确存在这个方法)。只有当字符串列表中完整包含一个字符串的时候,IsInList方法才返回true。
开始单元测试
您可以使用TestDriven.Net运行测试,单击鼠标右键并选择“Run Test”(如图3-6所示),如果您没有或者无法使用TestDriven.Net,也可以使用NUnit程序。您也可以在TestDriven.Net中使用相同的方式来做静态单元测试,但NUnit GUI不支持静态单元测试。所以,我在Program.cs(或者是后面项目中使用的UnitTesting.cs类)中添加单元测试来支持所有用户和XNA Studio Express。TestDriven.Net可以用来进行动态和静态单元测试,但2.0 版本之后您必须把[Test]特性从静态单元测试中去掉,否则无法正常工作(本书中的静态单元测试都没有使用[Test]特性)。
如图3-6
TestCase 'M:XnaBreakout.Helpers.StringHelper.StringHelperTests.TestIsInList' failed:
NUnit.Framework.AssertionException
at NUnit.Framework.Assert.DoAssert(IAsserter asserter)
at NUnit.Framework.Assert.IsTrue(Boolean condition, String message, Object[] args)
at NUnit.Framework.Assert.IsTrue(Boolean condition)
C:\code\XnaRacer\Helpers\StringHelper.cs(1387,0): at
XnaBreakout.Helpers.StringHelper.StringHelperTests.TestIsInList()0 passed, 1 failed, 0 skipped, took 0,48 seconds.

图3-7
黄金法则
这里我不准备写太多关于单元测试的东西,因为第二章已经讨论了最基本的规则,它们也适用于动态单元测试。当您开始写第一个单元测试的时候,要紧记下面的这些规则:此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。