缘起

碰到过一个面试题:升级某卡牌=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


↙↙↙阅读原文可查看相关链接,并与作者交流