自动化测试:游戏项目中的自动化测试和持续集成



游戏项目中自动化测试和持续集成


blueski推荐[2005-7-28]
出处:51cmm 希赛网
作者:不详


现在许多游戏项目要么跳票严重要不就是发布时Bug多多当然这样现象并不仅存于游戏工业例如根据2001Standish集团发表那份 声名狼藉报告“极度混乱”所表述70%以上软件Software项目要么被取消要么严重超时和超支然而游戏是软件Software开发复杂性最佳代表区别技能人需要 协同工作这也就是某些人所说游戏项目中高风险原因所在

  软件Software项目延期、Bug满天飞和失败原因是多种多样但看起来除了随产品特性不断变化的外测试和品质管理是永恒问题以我们经验来看相当多数游戏开发工作室完全依靠人工方式来测试游戏引擎、开发工具和游戏代码几乎没有采用自动化过程测试很巧在2002GDC圆桌会议:游戏中纯软件Software工 程只有18%和会者表示他们参和项目采用了自动化测试

  在2000年我们客户当时新成立中间件公司对我们3D引擎稳定性和大量BUG抱怨频频我们第次想到了自动化测试直到那时每当完成 个新特征我们还是依靠人工测试并且使用这些特征开发出技术演示供市场部使用我们在彻底分析了情况后得出以下结论我们软件Software质量问题主要和我们测试 思路方法有关:

  *人工测试不够全面和彻底它仅仅花费了很多时间 代码在修改或添加的后它本应运行预定义人工测试集来保证修改不会产生新问题人工测试花费时间越来越多并给开发者带来挫折感打击他们执行测试 积极性而且测试工作量使得开发者不愿意改进或优化现有代码

  *当开发者测试他们自己代码时他们总是不愿意(潜意识?)执行最苛刻测试用例因此就导致了最有可能出错的处也是最不可能被全面测试到这样情形

  因此我们决定采用自动化测试从开发个新SDK部件开始结果是鼓舞人心最终我们把它推广到所有SDK部件开发中去测试框架极限编程由Kent Beck和Martin Fowler整理总结系列思路方法和经验带来了自动化测试流行般来说自动化测试指无需用户干预用来验证软件Software产品中功能子集代码和数据它可以是用来测试某个特定类思路方法(通常称为单元测试)也可以是用来测试功能性集成测试(功能测试)

   为了促进自动化测试进程有许多开源代码单元测试框架比如CPPunit(C专用)或Nunit(.Net专用)这些测试框架提供了GUI来 运行测试集并提供测试结果反馈根据你项目也许需要根据你游戏进行些额外功能扩展和自定义例如支持跨平台这些测试框架内容个单元测试 对应测试类由多个单元测试组成并且包含个开始和结束测试思路方法(例如载入和卸载幅地图)这些测试类可以放在分离执行文件中例如 DLL文件也可以和主项目在除此的外测试类应该存放在产品代码的外文件中这样他们就可以很方便从版本发布中移除

  物理引擎简单测试代码如果任何个VTEST条件没有满足那么测试就失败该测什么?当要决定测试范围时实用第般来说为简单功能编写单元测试是没有意义比如常见getter和ter思路方法为了让自动化测试物有 所值被测试代码至少应该是可能会产生比如发射束穿透游戏场景光线并且返回它穿过任何几何物体思路方法(光线测试)然后将返回结果和 编写测试用例作者提供预期结果作比较

  到底是只为类公用 接口编写测试用例(黑盒测试)还是要兼顾类私有成员(白盒测试)个有争议问题通常来说黑盒测试比白盒测试粗糙它们只能检查个操作最终 结果不能检查内部中间状态它们对于被修改测试代码比较迟钝刚才提到光线测试功能可能被全部重写(比如原先版本运行效率不够)但是它返回结果没有变化这时白盒测试用例就需要跟着重写然而黑盒测试可以继续用来检测代码修改后所产生结果是否和原先

  因此我们认为自动化测试中测试范围只要包括类公有成员就够了毕竟内部修改比它接口修改要频繁得多



回归测试

   特别是在游戏开发领域大多数情况下把测试结果和用例编写者提供数据手工作比较是不太现实例如检测和复杂几何体碰撞交点人工提供相关测 试数据几乎不可能相反将测试结果和早期代码产生结果数据相比较被称为“回归测试”用例编写者可以评审参考数据例如使用简化图形碰撞物体如果被证实是正确它就可以直用于测试这样自动化测试可以帮助你确认新代码产生结果和原先

   代码功能测试会生成非常复杂输出数据比如游戏图形渲染引擎回归测试是唯可行自动化测试以图形渲染引擎为例所有图形测试以输出最终平台相关图形文件为结果旦自动化测试开始运行渲染出来图形文件和样本图形文件逐像素进行比较如果有差异那么测试失败为了减少样本图形文件存占用你可以使用图形快照来进行测试

  图形回归测试优势在于即使是肉眼难以发现微小差异也不会被漏掉除非人们对这个场景非常熟悉否则很难会有人注意到场景中缺失个阴影或个物体或者某个光源R值和B值被错换了而回归测试就不会放过任何个这样



   必须注意到任何情况下回归测试样本数据都是自动生成样本数据也许是平台相关特别涉及到渲染输出时候因此它也许要被生成多次即使是这样当渲染通道发生变化导致生成图形文件有所改变样本数据也要重新生成为了不打击开发者编写回归测试积极性要做到只需点击框架用户界面上个按钮就可以重新生成新参考数据

  如何把所有整合在

  包括游戏在内所有应用完整测试集合包括单元测试和回归测试单元测试适合于测试底层功能性、基础库文件和平台类库上层各种功能特征集成测试可以使用回归测试根据结果你可以有选择重构或优化你逻辑或引擎代码回归测试旦失败你会马上发现出问题地方单元测试失败可以让你精确定位出错的处

  知道代码被你编写自动化测试覆盖得范围是非常有好 处你可以使用代码覆盖率调查工具(BullseyeCoverage/AQtime)代码覆盖率分析会告诉你代码哪些被也可以提示你测 试集合中疏漏的处测试覆盖率应该是多少无法精确定量尽管它取决于被测试代码细小思路方法无需测试调试用也不必测试并且几乎所有项 目都会包括些“死”代码也就是不会被代码那么这些代码自然也不用测试总而言的现实中我们见过使用自动化测试游戏和中间件项目中 测试覆盖率大致是55%到70%

  编写友好测试代码

  必须承认并不是所有代码都能使用自动化测试以单元测试为例严格面向对象良好类和模块化封装设计可以大大提高它测试效率接口越多为它编写单元测试就越多同样过多使用C友元也会增加编写难度甚至无法为该类编写(黑盒)单元测试用例

  在写代码时候要时刻牢记保持良好测试性在开发过程中就会变成可行但是单调乏味工作有时候它需要很好结构性要在游戏开发中使用以下几点必须牢记:

  *所有回归测试都取决于明确行为比如使用随计算法寻径系统可以提供化随机种子公共思路方法使得角色行动决策更复杂多变这个思路方法在随后测试中可以被用来确保角色始终选取同样路径

  *同样回归测试中要避免和帧数相关情况;否则有真实物理特性物体或渲染输出也许会和以前数据区别特别是当结果来自区别机器或者区别编译条件(debug 和release)在测试时使用恒定虚拟帧数就可以避免这样问题

  * 严重依赖于用户输入软件Software很难测试比如游戏内置编辑系统或者游戏工具这样把UI 和逻辑代码严格区分开会有所帮助在我们游戏工具里 UI界面里每个用户动作会执行条或多条简单脚本指令每条脚本指令可以很明确重现用户原意这样测试用例可以简单执行这些指令并且和样本数据 作比较就可以(比如导出地形文件)

  也可以使用GUI捕捉工具来测试UI但我们发现这并不是个好办法UI会经常改变哪怕个按钮仅仅移动几个像素也会使捕捉软件Software失效GUI捕捉工具也许会帮倒忙

  有关测试疑问:我们真可以节省时间么?

  多数情况下个开发团队(Team)想要在开发过程中使用自动化测试大多数成员都会对它抱以质疑态度毕竟和其花这点时间写测试用例还不如去写逻辑和引擎 代码根据我们在游戏和其他领域工作中使用自动化测试经验来看编写测试代码会额外增加30%工作量初看在时间和资金上这也许是很大开销然而你要意识到这样做省去了人工测试所花费时间

  自动化测 试可以看作在开发前期投入在开发过程中赢利大多数代码修改包括Bug修改都可能会引入更多问题导致宕机所以理论上说旦代码有所改变就必须测试所有可能被影响代码自动化测试无需人工干预就可以完成它们缩短了开发过程而且由于自动化测试可以简单快速发现修改代码是否能有效地运行因此也就鼓励开发者优化和改进现有代码

  对我们来说自动化测试帮助开发者编写更稳定和可靠代码哪怕是开始对它抱有怀疑态度开发成员也欣赏它所提供早期反馈特性在开发过程中它也可以更早 发现Bug开发者工作压力和负荷随着项目开展日益加大尽早发现和解决Bug也可以避免给开发关键时期带来额外压力

  在开发Vision引擎时候我们收集了些数据来研究为提高代码稳定性而实施自动化测试有效性2001年早期全部依靠人工测试引擎第个 release版本开发完成尽管我们已经进行了很全面测试但是每个月我们在线技术支持数据库依然会收到上百个来自客户Bug报告2001年 9月我们对已有引擎功能和新增特征实施自动化测试这样即使我们现在工作量很大开发进展也很正常每月Bug报告数量锐减(现在大概是5到10个)

  必须强调这些图表只是反映了单元测试用例数量和每月Bug数量两者的间相互关系不能将它理解为必然因果关系当然从2001年到2004年我们在如何编写健壮代码上学到了很多在这段时间内开发团队(Team)人数变动频频但是这些明显差异足以介绍说明稳定性提升部分归功于使用了自动化测试



游戏中自动化测试局限性

  尽管使用自动化测试对于游戏开发来说获益匪浅但是也有其局限的处显然很难用它来测试游戏平衡性也不太可能用它来测试游戏性和画面美观性在这几年里我们整理总结了些编写自动化测试要点重点如下:



  *测试最重要模块(比如最复杂和最常用)对那些最有可能出问题或者不会破坏原先设计重构任务进行自动化测试性价比最高

  *当上层功能性测试难以进行时候把精力集中在区别子系统上例如你也许不能通过自动化测试来验证AI系统是否正常工作但你可以测试当个怪兽体力低于定数值时候它是否会“投降”

  *用压力测试来验证你代码强壮性如果你游戏在极端条件下运行很好比如每秒有2000个怪兽出生和死亡个场景中同时放入500个有真实物理特性物体幅地图轮流载入200次那么玩家作些异常操作时宕机可能性就会小很多

  *在修改Bug前也为它编写测试用例这样可以确保这些Bug在今后版本中不会重现

  *回归测试例如图像或状态比较使用指定测试场景要比使用产品地图更容易维护如果你认为测试用产品数据可能会经常变动那么你最好使用小测试场景否则不断生成新参考数据会使得开发团队(Team)产生疲倦和厌烦情绪

  * 测试用例越简单越好不要奢望有非常大覆盖面搭建个易维护和可扩展自动化测试是个长期任务般来说“底层”代码例如算术、碰撞检测和渲染更容易进行自动化测试对于游戏性和完整游戏测试来说还是需要经过QA人员亲自测试当然QA部门注意力也要从技术转移到和游戏性相关问题上去“到A房间后通风口前面箱子太高了所以出不去”这样报告就会取代“当我角色转动时候屏幕上出现了很多扭曲 3角面”

  持续集成

  在个复杂软件Software项目中引入自动化测试你会发觉运行它也需要时间我们看到些项目甚至需要几个小时如果让开发者在他们开发用机上运行测试会完全占用他们机器影响工作那么结果就是他们不去运行测试用例很显然没有被运行用例是没有任何价值

  解决思路方法就是搭建台或多台专用自动化测试机它同时还运行版本管理软件Software(Subversion/CVS/Perforce)旦发现提交了新代 码那么代码就会被Check out并编译测试用例也会自动运行最后系统会将测试结果报告以email形式自动发送给最近提交代码开发者

  完全自动化、重复 build和测试过程这种过程每天运行多次在极限编程中我们把它称为:持续集成为了更好实行持续集成像 Cruise Control或者Anthill这样开源代码工具可以将版本管理软件Software和自动build工具例如ANT整合起来使用这样工具 可以很轻松搭建适合自己持续集成系统

  我们发现搭建专用持续集成服务器使得开发过程变得更顺畅开发者可以更专注于自己工作和此同时测试可以被很好运行旦提交了代码持续集成系统会自动通知开发者和项目经理(project manager)因此开发者也可不必为此分心自动化自动化!

  自动化测试和持续集成使用为我们在游戏和工具开发上带来了极大收益例如持续集成服务器根据Wiki中变化每天自动生成CHF (windows帮助文件)文件而且使用ANT和CruiseControl来制作软件Software自动分发包会非常容易这样用最新代码(或最新 tag)创建个完整分发包就是举手的劳

  自动化过程中自 动化测试执行例如测试框架中常规单元和回归测试他们不是用来检查而是用在相同环境下得到测试结果来衡量和比较引擎性能(系统配置结果以 XML文件格式存放在版本管理软件Software系统上)如果当前结果比参考结果差很多那么测试失败反的它就成为了新参考结果

  性能测试是种特殊回归测试当引擎代码被重构我们通过它来确保修改不会降低引擎原有性能这样就迫使我们时刻关注代码运行效率和对代码优化工作可以避免遇到在实际运行中速度突然变慢现象发生

  结论

  根据我们经验使用自动化测试和持续集成可以使开发团队(Team)工作更有效而开发出更好、稳定、简单软件Software而且减少人工测试也可以减少开发团队(Team)压力和工作负荷可以在开发过程中尽早发现Bug

  当然自动化测试不会使你游戏想当然成为畅销品但毋庸置疑它会使各类开发人员甚至玩家活得更自在









Tags:  自动化测试框架 什么是自动化测试 自动化测试工具 自动化测试

延伸阅读

最新评论

发表评论