自动测试游戏

自动测试游戏

Automated testing a game

您将如何向游戏中添加自动测试?

我相信您可以对游戏引擎的许多功能(网络,对象创建,内存管理等)进行单元测试,但是可以自动测试实际游戏本身吗?

我不是在谈论游戏元素(例如Protoss在地图X中会击败Zerg),而是在谈论游戏和引擎之间的互动。

介绍

在游戏开发中,引擎只是游戏的平台。您可以将游戏引擎视为操作系统,将游戏视为可以运行该操作系统的软件。游戏可以是脚本的集合,也可以是游戏引擎中的实际子例程。

可能的答案

我的想法是这样的:

您将需要确定性的引擎。这意味着给定一组输入,输出将完全相同。这将包括使用相同的输入来植入随机生成器。

然后,创建一个包含几个角色的准系统级别,头像/用户可以与之交互。从小处开始,然后在开发更多交互时将对象添加到关卡中。

创建一个遵循路径的脚本(测试寻路)并与不同的对象进行交互(存储结果或预期的行为)。该脚本将是您的自动化测试。经过一段时间(例如一周)后,请运行脚本以及引擎的单元测试。


内在游戏中的这篇帖子可能相关/有趣。


Riot Games上有一篇关于对多人在线RTS游戏英雄联盟(LoL)使用自动测试的文章。

根据开发人员的说法,游戏代码和游戏平衡每天都有很多变化。他们构建了一个Python测试框架,该框架基本上是一个更简单的游戏客户端,该客户端将命令发送到运行LoL游戏服务器实例的Continuous Integration服务器。然后,服务器将命令的效果发送给测试框架,从而允许测试响应。

该框架提供了一个事件队列,该队列记录了特定时间点的事件,数据和效果。本文将其称为"快照"。

本文介绍了一个法术单元测试的示例:

设定
1.赋予角色能力。
2.在中路(地图上的某个位置)生成一个敌方角色。
3.在中部车道上爬行。 (在LoL的背景下,小兵是每支部队的一部分,它们是弱小的不可控制的角色。它们基本上是经典的饲料,是敌方部队的经验和金钱之源。但是如果任其发展,它们会压倒对方球队)
4.将角色传送到中路。

执行
1.快照所有变量(例如,玩家,敌人和正常角色的当前生活)。
2.施放咒语。
3.在一个敌方角色上激活该法术的效果(例如,某些法术会在命中时触发)。
4.重置该法术的冷却时间,使其可以立即再次施放。
5.施放咒语。
6.激活该法术对小生物的影响(在LoL的背景下,大多数法术在小生物上使用时会有不同的计算)。
7.拍摄另一个快照。

校验
从第一个快照开始,重播事件,并断言预期结果(从游戏设计师的角度来看)是正确的。可以验证的事件示例包括:伤害在咒语的伤害范围内(LoL使用随机数为攻击提供方差);与玩家角色和小兵比较时,可以适当抵抗伤害,并且在其中施放咒语其有效范围。

该文章显示,从普通游戏客户端查看测试服务器时,可以提取测试视频。


已经在另一个答案中提到了《两个游戏的力量》中的一篇文章,但是我建议阅读其中的所有内容(或几乎所有内容),因为它们的确写得很好,并直接应用于游戏开发。关于Assert的文章特别好。您也可以访问他们以前的网站,来自Games From Inside,其中有很多关于测试驱动开发的文章,这是极端的单元测试。

两个人的力量就是实现UnitCpp(一个相当受人尊敬的单元测试框架)的人。就个人而言,我更喜欢WinUnit。


我曾经做过与您的想法类似的事情,并且非常成功,尽管我怀疑它实际上更多地是系统测试而不是单元测试。正如您建议的那样,您的随机数生成器必须使用相同的值作为种子,并且每次生成的序列都必须相同。
游戏以50hz的周期运行,因此计时不是问题。我有一个可以记录鼠标单击和位置的系统,并使用它来手动生成一个"脚本",可以对其进行重放以产生相同的结果。通过消除计时延迟并关闭图形生成,可以在几秒钟内复制一个小时的游戏时间。
最大的问题是对游戏设计的更改会使脚本无效。

如果您的准系统空间包含的逻辑与一般游戏无关,那么它可能会很好地工作。引擎可以在没有任何用户界面的情况下启动,并在初始化完成后立即启动脚本。测试崩溃的方法很简单,但是更复杂的测试(例如将字符放置在正确的位置)会更复杂。如果脚本的记录足够简单(就像在我的系统中一样),则可以非常轻松地对其进行更新,并且可以非常快速地设置用于测试特定行为的特殊脚本。我的系统的另一个优点是可以在游戏测试期间使用它,并且记录了事件的确切顺序,从而使错误修复更加容易。


Values are so random within the gameplay aspects of development that it would be a far fetched idea to test for absolute values

但是我们可以测试确定性值。例如,单元测试可能使Guybrush Threepwood移至门(寻路),打开门(使用命令),失败,因为他的库存中没有钥匙(反馈),选择门钥匙(寻路+库存)。管理),然后终于打开门。

所有这些路径都是确定性的。通过此单元测试,我可以重构内存管理器,如果它某种程度上破坏了库存管理例程,则单元测试将失败。

这只是游戏单元测试的一个想法。我很想知道其他想法,因此,是这篇文章的动机。


我已经写了一篇关于该主题的论文-
http://download.springer.com/static/pdf/722/art%253A10.7603%252Fs40601-013-0010-4.pdf?auth66=1407852969_87bc2e71ad5228b36738f0237084ebe5&ext=.pdf


http://flea.sourceforge.net/gameTestServer.pdf

这是有关在游戏中实现功能完善的功能测试器的有趣讨论。

术语"单元测试"表示正在测试"单元"。这是一回事。如果您要进行更高级别的测试(例如一次测试多个系统),通常称为功能测试。可以对游戏的大部分内容进行单元测试,但是您无法真正测试游戏的乐趣。

只要您的测试可能是模糊的,确定性就不是必需的。例如。"使角色受到伤害"与"使角色失去14.7生命值"相对。


如果您使用的是XNA(这个想法当然可以外推到其他框架),则可以使用游戏中的单元测试框架,该框架允许您访问单元测试中的游戏状态。这样的框架就是Scurvy.Test :-)


如果您正在测试渲染引擎,我想您可以渲染特定的测试场景,进行屏幕截图并将它们与参考测试渲染进行比较。这样一来,您就可以从视觉上检测引擎的变化是否有任何破坏。您可以为声音引擎甚至动画编写类似的测试(通过比较一系列帧)。

如果要测试游戏逻辑或场景进度,可以通过测试脚本变量的各种条件来实现(假设您使用脚本来实现大多数场景和故事方面)。


这并不能真正回答您的问题,但我正在收听Microsoft上有关Pex的播客,该播客与您提出的解决方案具有相似的功能,当我在听播客时,我记得我认为想看看是否真的很有趣它将能够测试游戏。我不知道它是否能够特别为您提供帮助,但是也许您可以看看他们使用的一些想法并将其应用于您的单元测试。


推荐阅读