游戏测试之接口工具篇(下篇)

发表于:2016-10-28 11:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:煎饼的博客    来源:51Testing软件测试网采编

  上一篇分享了在做接口测试时,用到的一些工具软件,最终的感觉是,能用,但不顺手。最主要的原因是,发送请求后,没法很直观地查看服务端的返回结果,其次是使用起来,工作效率并不理想。
  在经历的几个项目中,最终都是使用了内部开发的接口工具,而每个项目的接口工具的原理和使用方式区别还挺大,在此分享下各个工具的设计思路。
  项目1
  2011年那会,刚刚从学校踏入测试坑,项目是一个SLG页游,前后端使用Socket通讯,数据交互采用Json格式,最初版本的接口测试是用WPE做的,后来服务端的主程MM在内网开了一个Web端口,可以接收Http Get请求,格式如下:
  http://192.168.22.248/sftx/gameSocket/send?u=playerId&c=protocol&p=port&params=param1|param2|param3
  参数的含义如下:
  u:玩家ID
  c:操作协议号
  p:服务器端口号
  params:参数列表,多个参数使用"|"连接
  举个栗子:玩家升级主城
  玩家ID:7001
  操作是升级主城:协议号110001
  参数列表:主城建筑ID是1001
  内网端口号:默认5001
  所以相应的Get请求是
  http://192.168.22.248/sftx/gameSocket/send?u=7001&c=110001&p=5001&params=1001
  把这个Get请求发送过去后,Web服务器会解析出相应的玩家ID,操作协议,参数列表,自动开启一个Socket连入内网游戏服务器,执行相应的操作,并返回处理结果。
  从此脱离了WPE,当时是用PHP围绕这个Web接口,做了一个调用页面,也实现了请求的新建,修改,分类保存,批量发送,并解析返回结果。
  基于这个接口,也实现了一些自动化的批量操作,如批量建号,批量升级等,对工作效率的提升也是很明显的,比如新建军团后,跑个批量申请入团,军团就满人了。
  这个模式的不足之处:发送请求后,因为Web那边会自行创建新的Socket连接,会自动挤号。
  项目2
  项目2是一个RPG页游,前后端使用Socket通讯,数据交互格式是AMF3。
  当时后端底层在重写ing,所以没空折腾一个Web端口给我调用~这个时候前端主程FF站了出来,提出了一个方案。
  游戏在网页上加载的时候,同时也加载一个测试用的js文件。
  执行接口测试的方式,是在Chrome的console窗口,输入已经加载的js函数sendCommand,把操作内容作为函数的参数,回车运行后发送给Flash客户端,Flash客户端接收后,解析出相应的操作ID和参数列表,执行后在console窗口打印出服务端返回结果。
  函数调用格式如下:
  sendCommand(“PackagesController”, “move”, 0, [“BACKPACK”,0,“BACKPACK”,30]);
  操作模块:PackagesController  背包模块
  操作行为:move   移动背包物品
  参数列表:[“BACKPACK”,0,“BACKPACK”,30]   从第0个格子移动到第30个
  这个模式的一个好处:接口测试的请求是前端解析后,自行发出的,所以不会被挤号。
  项目3
  项目3是一个回合制的RPG手游,客户端使用Unity,Socket通讯,数据交互格式是PB,作为工作室的第一款手游,这次前后端主程都一直很忙,接口工具在项目前期一直没有落实下来。中间也一度是用WPE和烧饼顶着先大概测下接口。
  随着两个项目以来的一些积累,这次开始自己尝试独立完成接口工具,工具需求规划如下:
  · 支持录制请求
  · 可以对录制的请求进行复制,删除
  · 解析请求里边的参数列表
  · 查看服务端的返回结果
  · 自动校验返回结果
  · 测试用例保存到本地
  实现过程中的一些积累在此记录下:
  录制的原理
  点击一个技能升级的按钮的背后发生了什么?
  · UI接收到点击请求,调用技能模块
  · 技能模块准备好参数列表,调用Server层的Send方法,生成一个请求
  · Server层接收后,对请求进行封装,加入校验key和请求头,压缩为PB格式,生成最终请求
  · 发送给服务端
  那么,要从哪里切入来录制请求呢?最终选择了在Server层接收后,对请求进行封装前,主要原因是,接口测试主要关注参数的不合理修改后,服务端能否做出正确判断,可以不用关心校验Key等其他信息,对请求进行修改后,点击发送,直接调用Send方法,底层就会完成新的请求封装和发送。省代码啊~
  于是乎,现在的问题是,录制的代码加在哪里?
  这个项目采用的方式,是直接在Send函数里边,嵌入了转存请求的代码。
  public int Send(int controllerID, int handlerID, IEnumerable<object> paramList, Action<GodResponse> callback) {
  // 煎饼加入
  TestCenter.AddRequest(new TRequest(controllerID, handlerID, paramList, callback));
  // 煎饼加入
  var request = CreateRequest(controllerID, handlerID, paramList, callback);
  SendRequest(request);
  return request.ID;
  }
  TRequest的定义
[Serializable]
public class TRequest :ICloneable {
int controllerID;
int handlerID;
IEnumerable<object> paramList;
Action<GodResponse> callback;
public TRequest(int controllerID, int handlerID, IEnumerable<object> paramList, Action<GodResponse> callback) {
this.controllerID = controllerID;
this.handlerID = handlerID;
this.paramList = paramList;
this.callback = callback;
}
public object Clone() {
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
  这个做法其实不合理,因为我们项目的测试代码并不提交到项目的代码库,每次更新代码,都会出现冲突,更合理的方式是前端提供一个发送请求的事件,测试代码这边进行监听(下个项目已使用这种方式)。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号