如何在游戏引擎中进行单元测试?


23

令我感到羞耻的是,我从未编写过适当的单元测试,只是编写了一些小的,无组织的测试程序,在测试成功后将销毁这些程序。我对如何在游戏项目中执行单元测试一无所知。(我的语言是C ++。)

我是否应该为引擎中的每个子系统有一个单独的项目以及与此相关的测试,然后再有一个更大的项目/解决方案来构建实际的引擎?举例来说event,我的引擎中装有模块;我该如何处理?


一个有趣的问题,当您开发引擎时,测试功能非常容易,但是游戏测试中的大型项目呢?
Yevhen

2
不丢人:单元测试不是自动一件好事。
o0'。

1
如果您从未尝试过使用单元测试,那肯定是可耻的。
克里斯托弗·约翰逊

Answers:


18

首先,您需要一个单元测试框架。过去我曾经使用UnitTest ++Google Test。前者非常轻巧,后者功能更强大,但麻烦一些。如果您需要这种东西,它可以很好地与Google Mock集成。当然,还有许多其他选项:请参见此列表(由UnitTest ++的最终作者)和Wikipedia

单元测试是关于编写重点测试,以强调各种情况下特定的独立代码位(“单元”)。在某些情况下,您可以对所有内容进行单元测试,但要达到100%的覆盖率通常不切实际,尤其是在游戏中,可能会非常困难-单元测试渲染器输出是否在任何意义上,意义上或实用性方面都存在争议无论如何,都是“真实的”单元测试。

重要的是要记住,任何(自动)测试都比没有(自动)测试要好。因此,对于您的测试不是“真正的单元测试”这一事实,您不应该过分强调,并且为您仅拥有测试而感到自豪。单元测试框架通常还用于构建较宽松的“非单元”测试,因为它们包括用于打包测试和统一报告故障的功能。

我鼓励您复活旧的测试,并使用其中一个可用的框架将它们构建到测试项目中-您可以不时地(或自动将其作为发行或集成版本的一部分)轻松运行所有已运行的框架您的测试。为代码的某些部分编写新的测试对您很有用,例如,如果您发现可以用测试检测到的细微错误,则可以添加一个以捕获将来可能进行的任何回归。

您可能会发现,游戏中大多数适合单元测试的是较低级的实用程序代码。很好-这是基础代码,如果代码破裂,可能会干扰许多更高的层次。

您不会因为没有对代码库中的每个小功能和逻辑门进行测试而去程序员的炼狱,因此,不要花费过多的时间来编写测试。如果您要比为一开始编写模块花费更多的时间思考或花更多的时间为模块编写测试,那么您可能正在浪费时间。单元测试(通常是测试)是一种您学会适当使用的工具,可以帮助您,而不是您必须为所有事情执行的琐事。


3
If you have to [...] spend significantly more time writing the tests [...] than it took you to author the module...那么您的模块太复杂了。现在进行简化,您将在以后表示感谢!
杰西·特尔福德

3
@Jess很难测试的模块并不一定要简化。在很多地方,单元测试根本就不是时间的好用。这包括图形,其中输出可以有很大的变化并且仍然可以接受;将来不太可能更改的代码;或代码中,为方便单元测试而需要的那种抽象的,解耦的设计要丑陋得多,容易出错,性能较低或不太直观。
Casey Rodarmor

@rodarmor-同意。有一个合适的和不适合的滑动标尺。与所有这些答案一样,一个尺寸并不适合所有问题:)
Jess Telford 2013年

对于UnitTest ++,请访问github.com/unittest-cpp/unittest-cpp。其他所有内容都已过时。
Markus 2013年


4

“单元”是最小的可测试代码段,通常是单个函数或类。单元测试是另一段代码,它执行该代码单元以确保其行为符合预期。一个单一的代码单元可能要进行许多测试,以涵盖所有情况。

通常,测试不包含在项目的主版本中。而是有一个单独的测试构建配置,其中包括所有测试代码,并生成一个运行所有测试并报告结果的程序。一个测试框架将为此提供所有支架,尽管并非绝对必要,但仍建议使用。如果您完全不熟悉测试,最好先编写自己的即席测试装备,以确保您了解正在发生的一切。

用测试覆盖尽可能多的代码,对您不确定的代码进行优先排序,或者将易碎的代码划分为将来可能会破坏的代码。您应该经常运行测试,最好在每次代码更改后运行测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.