胡侃游戏自动化测试
 

2009-03-05 作者:开水泡泡 来源:开水泡泡的博客

 

申明一下,只是在这里抛砖引玉,各位如果有好的方法和建议,欢迎指正。

首先,据我了解,国内的游戏(MMORPG)行业(国外的我不知道哈),几乎还没有比较成功的游戏自动化测试体系,或许是我孤陋寡闻吧!有少数公司在做,但是效果都不很明显,结合我自己的做的一些经历和实际操作,小小的说说自己的想法。

1.目前市面上的一些测试工具如:lr,wr,qtp什么的不适合做游戏自动化测试,至少我没找到合适方法。个人理解是因为这个工具实际是通过简单录制或定制一些行为来实现自动化测试的,做游戏自动化测试,这些工具有几个重大缺点:

部署成本高:

自动化体系在server端很难部署,定制行为的时候几乎不能调用到游戏的接口,无法获得游戏实际运行的信息,预期结果不方便定制。如果是通过简单录制回放的话,效率不如手动操作好,对一些繁琐的行为,几乎是不现实的,而且这些工具对tcp/ip协议支持不如http协议好,有兴趣的同学可以去研究研究。

效果差强人意:

我之前用lr做了一下游戏自动化,不到一周我就放弃了,后来招了一个lr的新人,我在百般劝说下,他都没放弃游戏lr的自动化测试,结果3天不到,他也放弃了!游戏自动化测试本质目的是提高测试效率,用lr反而降低了测试效率,那么我们还用lr来干什么呢?这里我也不多说原因了,到后面我会提一下另一种方法的,主要说另一种方法的优势,而这种方法的优势恰好是这些工具的劣势。

2.几乎所有的游戏在前期架构设计上就没考虑到游戏自动化测试的需求,所以在游戏后期介入自动化测试几乎是不现实的。

3.公司没有足够的人力物力,或者说项目组就没有意识到自动化测试的意义,所以也无法开展。

4.测试自身的能力,很多(现在不是几乎了,有的游戏公司的测试还是很nb的)测试自身能力不足,或者接触不到游戏代码或其他需求无法满足,导致无法进行自动化测试。

接着,我主要说说游戏自动化测试对游戏架构的需求:

首先,如果在一款成熟运营的游戏中,试图让测试自动化起来,几乎是不大现实的。原因不外有二:

1.我要想在游戏世界里刷出一个怪或要取得一个player的信息,如果我们的开发人员没有暴露接口出来,请问,我们该怎么办?

2.我们要做一个自动化体系,是我们自己再去开发一个新的系统呢?还是用原来的系统?如果开发一个新系统,那么我可以告诉你,国内几乎没有那个项目老大允许你这么做,运营期的游戏,最重要是一个持续稳定,如果你插入你的开发量进去,我可以明确的告诉你,你会完全打乱你老大的计划。那好,那我们在原来的系统上改吧?对这一点,我相信有经验的同学都知道,去改别人的代码的效率远远低于自己开发的效率(如果是小改动,可能是达不到自动化的效果的)。

这2个原因是阻碍游戏自动化的主要因素,当然还有其他因素,比如对项目组对测试认识方面等等的问题,这些我不在这里讨论,这里只说说技术上的需求。

这一篇,我将会从游戏架构设计上大概谈谈,游戏自动化对架构的需求,下一篇会说说,成熟运营的游戏自动化可以做些什么。

在项目风格基本确定后,就是程序架构的设计了,如果在这个时候不考虑到测试的一些需求的话,那后期做起来就会很难。

一般来说,游戏设计分3大块:1.数据库设计。2游戏逻辑server。3 游戏的逻辑client。这里的server是广义的server,不同公司的设计是不一样的,不细分。游戏client就是指平时我们运行的,可以实际“玩”的游戏,运行在我们玩家的pc机上的可执行程序。

对于我们测试来说,其实可以把数据库独立出来,数据库和游戏的交互无非就是存取修改操作。在不考虑的性能情况下,自动化测试可以不考虑数据库,当然对于数据安全性等的操作其实属于策略问题。

其实我们实际做的自动化测试主要是游戏server的实际运行和与client的交互。这里再强调一下,自动化的本质是为了提高测试效率,所以我们只让计算机做他适合做的事情,而不是把所有的测试都交给计算机,那可能就本末倒置了,反而是为了自动化而自动化,没意义。

设计上要求务必达到:

1低耦合,高内聚

这个能简化我们实现测试的过程,又能让我们更准确的定位问题和回归问题。具体原因这里就不说了,可以去看看软件设计和测试的一些资料。

2.游戏运行要高透明,游戏运行的对象是可以给定条件获得,并且运行条件是可编辑的。

这个问题不能太深入,太深入可能公司就要找我麻烦了哈,大家原谅一下。这样设计的目的就是为了,我们可以定制我们的测试过程和预期结果。

3.通信是是可以设置和编辑的。

其实client与server的交互的本质是通过发送数据包来实现的。我们游戏人员通常说的协议其实是制的一个一个的数据结构,而不是tcp/ip之类的协议。实现这个的目的是我们在部署大量client与server交互的时候不需要运行我们的client,只需要一个发包client就可以了,而不需要弄上几千几万个物理client。

4.所有的接口在发布版本是关闭的。

这个是鉴于某公司之前出现了一次严重事故而增加的,之前某公司由于发布失误,导致外网玩家可以直接编辑游戏运行的一些数据,这个做起来也非常简单,在server上加一个宏就可以实现:ifdef _Debug define Test endif 就可以了。在编译发布版本的时候,就不会暴露这些高危数据出来,当然方式有很多,根据自己情况定是最好的。

接着,主要说一下哪些可以用来做自动化测试。

前面我大概说了一下游戏自动化测试的一些现状需求,这一篇主要谈谈游戏里面哪些可以做,哪些好做,哪些难做,哪些没必要做以及一些原因。欢迎拍砖哈,希望大家也谈谈你们的做法和优点。

我们在做游戏自动化测试之前,我们先假设我们的架构已经设计的足够好,允许我们能够通过我们的测试工具,获取游戏的运行状态并且修改游戏的状态。原本打算写到五就差不多了,后来应一些朋友的要求,我会大概说说游戏架构没有考虑到自动化测试的时候,自动化测试可以做的一些事情。

据我了解的情况,目前国内所有的网络游戏都是采用面向对象的方法设计和实现的,如果有不是的,我没接触过,也不知道用什么办法去做,所以再一次假设,我们的游戏都是使用的面向对象的方法设计和实现的,请记住,这里我再三提到对象这个概念。后面讲的一些东西将会围绕这个概念展开。

还是先说一下哪些东西不建议采用自动化测试吧:

1.表现类,以主观感受为主为测试目的测试对象。

大家都知道,计算机最喜欢做的是逻辑性计算,而不是人性计算。之所以不做,原因就是这类测试几乎无法定义预期结果,所以更不要谈测试结果了,如果没有测试结果,那么计算机做了什么呢?这种问题主要集中在client上,比如画面,音效,操作性,当然还有设计的游戏平衡性等等。这里标准其实就是:当人无法用逻辑语言表达出预期结果的东西,不要试图自动化。

2.性价比低,一次性劳动且开发量大的测试对象。

自动化的目的是为了提高效率,而不是为了自动化而自动化,也不是为了来表演某个人的技术能力。我见过某公司的一个朋友,曾经花了几大天的时间做了一个测试工具,仅仅是为了节省一个人半天工作量的测试工作。这种主要是需要做一个评估:这个测试工作是经常的吗?这个的自动化测试的开发成本是多少?我以前才开始做的时候,一个同事给我提了一个需求,让我单独给他做一个工具,用来检查策划新提的一个数据文件,这个数据文件只是他们的一个设计文件,而且文件内数据的关系只是有这个策划的心情来决定的,我当时傻不拉叽的给她做了(我估计我当时是色迷心窍)。而我花2天做的东西,她就点了一下鼠标,从此以后这个东西就永久的存储在工具库里了,不知道何年何月这个工具才能重见天日。因为我不知道将来是否有一天,还会有策划会按这个规则去设计他们的数据表。说明一下,这类数据文件之间的关系完全是通过数据来对应,一旦对应关系发生改变,测试代码也需要改变,所以重用性不高,而且这个仅仅是他们拍脑袋的结果,并不是我们实际运行在游戏中的数据文件。

说了这么多,现在开始说哪写东西适合做自动化测试:

计算机喜欢干重复性逻辑活动,那我们就让他干这种事情吧。

简单算一下效率,假设某个测试工作需要5人*2小时/天的工作量,而且每天都是重复的工作,比如我们做游戏的,一般游戏发布前都需要对版本质量进行review,这个事情如果我们可以在我们下班后,让计算机去做,会是多么幸福的一件事情啊!假设游戏生命期3年,每周发布一次版本,每次发布前需要10个小时的绝对工作量,那么3年就是10*52*3/7=223,也就是要花费一个人223天的工作量,这其实是一个人一年的工作量了,而我们开发这个东西只需要10天!

我们做自动化测试的时候,一般做通用性的东西,也可以叫做平台类的工具,在这个平台上,我们再设计自己的行为,通过这个平台作用于游戏,再通过平台将结果返回给我们的测试代码。

而这个平台就要回归到前面所说的对象概念了,我们运行在游戏种的一些逻辑其实都是一些对象的行为。结合我们的测试可以说其实我们测试就是侧某一个对象在某一个状态下,是否产生了某种行为和没有产生不应该的行为。有了这个概念,我们设计自动化测试思路就清晰了。

首先,这个平台我在二里面没提出这个说法,但是其实就是这个概念。这个平台主要是实现:实现测试代码和游戏的通信,通过这个平台,我们测试代码可以获得和修改游戏运行的环境。

这个平台是长期维护的,当游戏一些逻辑发生变化的时候,平台可能需要相应的变化,否则可能会阻碍测试。平台是通用的,测试代码是针对具体的测试对象而设计的。

我们假设现在需要测试一个任务(下列是我将这个任务分解了一下,为条件和步骤哈):

1.找a npc能接取到 a1任务。

2.找其他npc不能接到a1任务。

3.角色等级>=10级。

4.角色有道具b。

5.角色pk值大于5.

6.扣除b道具后,角色接得a1任务。

7.角色杀20个怪后,可以交任务。

8.任务不能重复做。

接下来,我大概说说测试思路哈:

player = GetPlayerByName('xxx') 首先获得一个player对象,这里前面就是谈到的对象概念了。

player.SetLevel(10) 设置player对象等级

player.AddItem(b,n) 设置角色身上道具b

player.SetPkValue(5) 设置pk值

player.ChangePos(x,y,z) 将player传送到npc那

player.GetMenu(npc,choice) 选择和npc对话和具体选项。

if player.GetItemNum(b)!=n-1 or player.task[taskid].status:判断是否正确接到任务和扣除道具

Error(player) 如果错误,则返回player的数据(包含任务等数据)

return false

好了,这里说个思路就是了,我们实现自动化测试的思路大概就是这样的。当然其实这个还可以进一步做的,相信大家见过一些地图编辑器和任务编辑器,我现在可以说一个,其实我们自动化测试的时候可以做测试编辑器。思路还是和上面说的一样。

只是要做这个测试编辑器,就需要更好的设计优化我们的测试平台,将我们测试行为分离成指令+数据的形式。比如上面说的找npc对话接任务,我们平台可以设计一个接口:GetNpcOption(npcid,choice,player)实现把player传送到npcid那并选择某个选项。这个接口首先需要能找到这个npcid的npc,然后吧player传送到这里来,然后player选择这个choice。好了,我们假设我们这个也已经做过优化了。接下来,我们设计用例吧:

操作过程

player.level=10

player.SetItem(b,n)

player.pkValue=5

GetNpcOption(npcid,choice,player)

预期结果:

player.GetItemNum(b)==n-1 and player.task[taskid].status

测试结果就拿来和预期结果比较就可以了。相信这样说大家已经明白了这个测试编辑器怎么做了,就是将我们行为和数据简化成指令+数据,我们可以通过这个编辑器来编辑测试行为,而我们的测试平台需要能解释这些行为。这里测试平台要吧这些行为翻译成游戏能理解的数据。这个最初我以为开发量会很大,但实际做下来,这个翻译行为比预想的轻松得多(当然,前提还是架构充分考虑到这些问题哈)。

好了,我们现在可以把精力充分花在设计用例上了,我们可以把最擅长设计用例的人充分利用起来,让少部分人去维护吧,这样,我们就可以把最合适的人放到最合适的岗位上去了。

为了测试更全面,我们还可以更进一步,让我们测试编辑器,可以设计一些随机行为,这里随机行为一个是数据的随机,一个是操作顺序和操作的随机(前提是这些操作随机后是游戏平台能识别并翻译的)。我们还可以定义只要不满足什么条件就是测试不通过的。这样只要我们的测试覆盖率就直接受我们设计测试影响了。一些人无法实现的大量,重复的,偶然的也可以做了。

一些朋友问我:能不能再具体点?其实已经很具体了,自动化是一种思想,就像lr,qtp一样,其实工具并不重要,关键是你的思路,有了思路,一切就都有头绪了。当然有的东西可能不适合你们。毕竟不同公司条件或做法都有区别。


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织