游戏测试 交流----PB 数据的协议测试

陈随想 · 2021年08月04日 · 最后由 陈恒捷 回复于 2021年08月12日 · 4591 次阅读

缘起

碰到过一个面试题:升级某卡牌=A+B+C(三个材料数量固定只能是 1)。简单说就是三个数量为 1 的材料可以升级某卡牌(不需要额外金币或者其他资源)。并据此说一下协议测试用例。

由于现在所在项目原因,我很自然代入了 PB 数据作为通信协议数据,然后回答的时候有个点和面试官冲突了:他认为需要测试 A+B+C+D,也就是数量为 4 的情况,我认为不需要去测试这个情况。我本人不是很擅长被面试,临场发挥是弱项(面对别人说话就脑子有点紧张),但是我觉得我没有问题。这里事后总结一下想法,不谈面试问题,只谈由面试引出的协议测试设计问题,同时也希望行业老大哥交流一下。

PB 数据的思考

面试官想要缩短考的范围,指定了固定数量是 1。但是我表达的是,item1:count1,item2:count2,item3:count3(这个涉及到我为什么认为不需要测试 A+B+C+D)。

首先说下协议内容为啥要有 count,即使你指定数量 1,协议内容也必须要有 count,这是因为扩展性原因。在涉及诸如卡牌升级系统的时候,往往不能因为需求指定了数量 1,就少了必须的 count 参数,这非常不利于以后的扩展。万一以后升级材料数量不是 1 了呢?

现在我们承认了 count 参数存在的意义,这就又引出了另外一个问题:那么是不是要考虑 item4:count4 的情况,万一以后多了材料 4 呢?这就非常没有必要考虑了,因为多了材料 4,理论上你的系统就要重新迭代,包括 UI 设计,布局设计(你得设计多一个格子,去给玩家把材料放进去了)。

接下来用 pb 数据来说下我设想的可能的协议结构数据:

message item {
    required int32 itemid = 1;
    required int32 count = 2;
}
message updatecard {
    required item material1 = 1;
    required item material2 = 2;
    required item material3 = 3;
}

面试官给我预先设想的结构,居然是List(协议内容为 [A+B+C])。当然,proto3 现在也支持ListValuemap<K,V>此类json mapping。但我认为此类卡牌升级指定了三种材料,协议数据设计就不应该用List,因为这样你不知道列表长度,不知道带了多少种材料了,就需要多一个len()去判断长度了。如果需求是要给不定数量的玩家发奖励,这种带有不定数量的情况,协议是可以用列表的。

基于以上想法,以及我设想的协议结构数据,我认为协议测试重点是itemidcount参数,而没有必要考虑 A+B+C+D,这种多了一个 D 材料的情况。客户端多了一个 D,服务器处理协议数据可能就出问题了:明明说好三个材料,你多发了一个,事先没声明,服务器根本不知道怎么去处理,会因为协议没对上直接报错或者返还 “错误内容” 给客户端了。我甚至认为itemid不需要测试空的情况,但是很遗憾,又和面试官冲突了。(在实际测试中,看到 required 字段,我很自然就不会去测试空的情况)

现在我又多了一个结论:不看具体协议数据结构设计去谈协议测试,有点脱离实际了。
@jiazurongyu 还请老哥指教

---------分割线----------
抱着疑问查了一下,又多了解了一些东西。
https://stackoverflow.com/questions/31801257/why-required-and-optional-is-removed-in-protocol-buffers-3
https://capnproto.org/faq.html#how-do-i-make-a-field-required-like-in-protocol-buffers

共收到 4 条回复 时间 点赞

web 开发来说,前端组建化的结果是,很多输入框的异常值边界值都很难出 bug 了,因为后端框架的成熟,开发也很难写出 sql 注入的问题了。这种例子太多了,大部分情况模仿相比推导是更经济的学习方式,一个老经验的测试方法,总是找不到 bug 的时候,自然会被放弃。但在变革发生时,只靠模仿也会跟不上变化。
每次编译 proto 的时候,不就像执行了一次测试嘛。

黑水 回复

受教了,老哥这番话点醒我了。感谢。

你说的例子中描述的 message 结构,实际上在实际业务中,一般写成这样
message ComposeData {
required int32 itemid = 1;
required int32 count = 2;
}
message updatecard {
required int32 TargetItemID =1;//目标 ID
repeated ComposeData ComposeData=2;//材料数组
}

用 repeated 字段来控制合成数量,需要用到几个就传几个 ComposeData。
所以是需要考虑 A+B+C+D 的。

额,你们面试聊协议测试,不是应该先确认好协议是什么的么?你和面试官设计的两种不同的协议方式,对应的测试点也不一样,也很正常。抛开协议实现讲协议测试,这样会出现理解偏差也很正常。

至于哪个更适合,得结合完整业务场景看。比如升级卡牌如果业务上预计后续会变得非常灵活,支持任意类型材料的任意组合(运营常用手段),那面试官设计的 list 类型,确实扩展性会更强,更符合业务长期的需要。

陈随想 关闭了讨论 09月13日 21:36
陈随想 重新开启了讨论 06月13日 15:09
陈随想 关闭了讨论 06月13日 15:13
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册