游戏测试 詹聪聪:游戏接口测试自动化实践

一江春水zcc · 2020年06月13日 · 最后由 gf 回复于 2021年10月14日 · 10701 次阅读

来 testhome10 天了,发了两篇质量保证的水文,全是理论,有些读者老爷希望我来点干货。那今天就发一个干货,这是我测试三年来关于游戏接口自动化测试方面的心血,必定全网唯一,希望大家多多支持,多多点赞!(长文预警)

1.背景

1.0 作者背景

先说一下我的背景,上海某游戏公司 QA,3 年游戏测试经验,虽然工作时间不长,但是接手过一个大型的页游项目和一个在研手游项目,对接口自动化方面有一定的思考和技术沉淀。

1.1 游戏测试行业的现状

国内的游戏测试行业目前普遍的是功能测试走天下,偶尔出来个 UI 自动化测试就了不得了。众所周知,UI 自动化开发和维护成本高,投入性价比很低,而游戏又是一种界面千奇百怪又元素布局纷繁复杂的软件,UI 自动化更是得不偿失,即使上马了自动化测试项目,往往都是虎头蛇尾,在维护方面难以为继。

据我的观察,游戏测试应该是落后外面 5 年的技术沉淀。为什么其它互联网企业,自动化测试满天飞,游戏测试行业依然如此原始。可能游戏行业已经被踢出互联网行业,划归为传统软件开发领域了吧。😆

1.2 接口自动化测试的难点

虽然我们游戏行业落后,但是我们游戏也有接口可以测试啊!既然可以接口测试,干嘛不自动化呢?提高测试效率,多好的事儿啊。好是好,但没人做啊。

1.3.1 人员素质

游戏测试薪酬普遍比同行低几千,基本上招的都是黑盒测试,技术能力薄弱,接口测试还能搞搞,你让他们开发接口自动化平台,抱歉,没那个能力。所以游戏测试做到最后,并不是成为技术大牛,大部分转游戏策划了。毕竟游戏是我测的,我还不了解嘛,照葫芦画瓢也能写个策划案出来。

1.3.2 通信协议特殊

对于大部分的游戏而言,客户端和服务端交互,都是基于 TCP 协议自定义传输协议。划重点,用的不是 HTTP 协议!接口测试所需的数据的发送、接收和验证功能都必须建立在:有一个完备的游戏客户端的基础之上,完备性体现在能够正确接收和处理异步消息(包括服务端的推送消息和接口返回消息)。

1.3.3 没有测试工具

由于通信协议的特殊性,相当一部分(只支持 HTTP 协议的)接口测试工具是没办法用的。所以游戏测试人员测接口,基本上都是各个公司开发人员编写的发包工具来测试的。开发大哥给你个测试工具就不错了,你还想怎么样?什么?要写个自动化测试工具?一边凉快去,没看到我正忙着嘛!

1.3.4 没有公司的支持

对于老板来说,游戏出 bug 有什么大不了的,给玩家补偿就好了,我要的是游戏能尽快上线赚钱,其它的一律靠边站。你让我开高工资招测试开发,还要花时间搞这些花里胡哨的东西,那是不可能的😆

另一方面,公司的预算,更倾向于原画、策划、前端,原画可以画皮肤卖,策划可以想玩法套路,前端可以把东西做出来,怎么说都是性价比更高。

1.3.5 其他

其实还有其他方面的不利因素,比如:立项时就没有考虑到以后要做接口自动化,设计的时候也不会在给予便利;没有 HTTP 协议的那种 restful API,没有系统化结构化的接口设计,测一个 case 要有一套复杂的前置动作等。(但是我觉得那都不是主要原因)

1.3 实现自动化的意义

既然上面有一堆不利因素,你为什么还要去做接口的自动化?

一个很重要的现实因素:因为项目组就我一个 QA,我不做自动化,意味着每次更新,我都要手动去做回归测试。程序员最讨厌的事情是什么:重复!当我做了实现自动化,我可以把节省下来的时间用来喝咖啡啊,多好!

还没怎么介绍干货呢,废话倒是讲了一堆😅,下面要进入正题。

2.做一个游戏客户端

理论上这个时候要讲接口自动化测试框架设计,但是现在连接口测试工具都没有,也谈不上设计自动化测试框架,先写个游戏客户端作为测试工具吧。

2.1 游戏客户端架构设计

游戏客户端

2.2 做一个 socket 客户端

2.2.1socket 客户端

这个好做,随便一个编程语言,都有网络编程,你照着例子,你就能写出一个 socket 客户端。以 python 为例:

import socket

class Client(object):
    def __new__(cls, playerId, game_server, certificate):
        cls.playerId = playerId
        cls.game_server = game_server
        cls.certificate = certificate
        cls.cache = b""
        return super(Client, cls).__new__(cls)

    @classmethod
    def server_connect(cls, server):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect(server)
        return sock

    def receive(self, sock):
        pass
    def send(self, *args, **kwargs)
        pass

2.2.2 数据封装

我们知道 socket 数据传递的形式是二进制数据流,一般接口数据是以 json 格式为主,这就涉及到了数据的封装。简单来说就是把 json 数据转化为字符串,然后再通过封装成二进制数据流。

对于数据封装,就涉及到了各个公司自定义的通信协议格式。我们自定义一个协议(对于客户端而言),收发的数据报文的格式如下:

数据报文

假如我要发送一个接口,数据如下:

"""
服务器id:10203
接口名称:store@buy
数据包id:5
数据内容:giftId=7392&useTicket=1&ticketId=357860382
"""
import struct

serverId = 10203
command = "store@buy".encode("utf-8")
packId = 5
packData = "giftId=7392&useTicket=1&ticketId=357860382".encode("utf-8")
packLength = 40 + len(packData)
# 最终发送的数据流
data = struct.pack(">ii32si{0}s".format(
    len(packData)), packLength, serverId, command, packId, packData)

接收服务端的推送就可以这样解析:

"""
接口名称:store@buy
数据包id:5
状态码:200
数据内容:{msg:"purchase success!"}
"""
import struct

# 假设接收到的数据流如下
cache = b'\x00\x00\x00Cstore2@buy\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\xc8{msg\xef\xbc\x9a"purchase success!"}'
packDataLength = len(cache) - 40
# 接收数据流
struct.unpack(">32sii{0}s".format(packDataLength), cache)

这里的状态码可以我使用了 http 的状态码,你也可以自定义一套。

2.2.3 数据压缩解压缩

前面的数据都是没有经过压缩的,现在压缩是数据传输的标配,一方面是为了节省带宽,另一方面是为了节省磁盘消耗。

在 python 中,二进制数据流压缩使用 zlib 库。对于我们的通信协议而言,值得压缩的数据,就是数据主体部分。

import zlib

packData = zlib.compress(original_data)
original_data = zlib.decompress(packData)

2.2.4 数据加密

大部分游戏数据不需要加密,但是特殊场景下也是需要数据加密的,比如登陆或者支付等场景。常规的非对称加密思路如下:

  1. 客户端和服务器端建立连接
  2. 客户端产生非对称密钥,将公钥传送给服务器端
  3. 服务器端通过公钥将密钥进行加密并传送给客户端
  4. 客户端接收到密钥并进行解密,双方开始通信

类似地,数据加密针对的是数据包体的部分,在 python 中使用 rsa 库对这部分二进制数据加密。

import rsa

def rsa_encrypt(string):
    (public_key, private_key) = rsa.newkeys(512)
    encrypt_string = rsa.encrypt(content, public_key)
    return (encrypt_string, private_key)

def rsa_decrypt(string, public_key):
    decrypt_string = rsa.decrypt(string, public_key)
    return decrypt_string

2.3 接口层

2.3.1 接口定义

接口定义在 Command 类中,单独的方法,参数一目了然,方便调用,也有利于拓展。

class Command(object):
    @staticmethod
    def store_buy(serverId, client, packId, giftId, useTicket, ticketId):
        client.send(serverId, "store@buy", packId, giftId=giftId, useTicket=useTicket, ticketId=ticketId)
    @staticmethod
    def store_info(serverId, client, packId):
        client.send(serverId, "store@info", packId)
commands = Command()

2.3.2 接口处理

自定义一个 Handler 类处理服务端推送消息处理器。work 是事务处理方法,test 是测试时的数据验证方法。

class Handler(object):
    def __init__(self, robot):
        pass
    def work(self, robot, response_data):
        """
        事务用处理器
        """
        pass
    def test(self, robot, response_data):
        """
        测试用处理器
        """
        pass

class StoreBuy(Handler):
    def work(self, robot, response_data):
        state = response_data.get('')
        commands.store_buy(serverId, client, packId, giftId, useTicket, ticketId)

class StoreInfo(Handler):
    pass

2.4 消息处理层

这部分已经是游戏客户端的逻辑了。

2.4.1 客户端数据

将客户端定义为 Robot 类,客户端与服务端的交互数据都放在这个类中。

import multiprocessing

class Robot(object):
    inputs = list()
    outputs = list()
    socks = dict()
    playerData = dict()
    packId = 1
    def __init__(self, client):
        self.client = client
        self.queue = multiprocessing.Queue()

2.4.2 消息监听

使用 select 模块,由于是系统暴露的接口,效率比较高。我的破电脑是 windows 的,没办法用 epoll。在做压力测试的时候,大量的游戏客户端跑在一个机器上,用 epoll 效率就高很多了。

import select

class Robot():
    def message_collector(self)
        while self.inputs:
            print(self.inputs)
            readable, _, _ = select.select(self.inputs, [], [])
            for sock in readable:
                response = self.client.receive()
                self.queue.append(response)

2.4.3 消息处理

Handler 类中,取所有接口处理器字典作为 handlers。

handlers = {
    "store@buy": StoreBuy,
    "store@info": StoreInfo
}

Robot 中添加接口处理机制:

class Robot(object):
    @staticmethod
    def handler_selector(cmd):
        return handlers.get(cmd)

    def message_handler(self):
        while True:
            response = self.queue.get()
            handler = self.handler_selector(response[0])
            handler.work()

3.如何实现接口自动化

其实当你完成了游戏的客户端,那么测试的设计,就是小菜一碟了,理论上就是运行过程中的数据验证问题。

3.1 设计思路

自动化测试设计思路

3.2 测试用例

3.2.1 代码部分

在 Handler 中添加 test 方法,正常逻辑是走 Handler 的 work 方法,测试验证逻辑走 test 方法。

class Handler(object):
    def __init__(self, robot):
        pass
    def work(self, robot, response_data):
        """
        事务用处理器
        """
        pass
    def test(self, robot, response_data, expect):
        """
        测试用处理器
        """
        pass

class StoreBuy(Handler):
    def test(self, robot, response_data, expect):
        state = response_data.get('state')
        if state == expect['state']:
            print("test pass")
        else:
            print("test failed")

3.2.2 数据部分

测试用例主要有 4 个部分:id,接口名,发送的数据,期望返回数据。

testCases = [
    {
        "id": 163,
        "command": "store@buy"
        "data": {"giftId": 126, "useTicket": 1, "ticketId": 43992687}
        "expect": {"state": 200}
    }, {
        "id": 164,
        "command": "store@buy"
        "data": {"giftId": 126, "useTicket": 1, "ticketId": 0}
        "expect": {"state": 402}
    }
]

3.3 测试过程

3.3.1 执行逻辑

我们的验证逻辑是写在处理器的 test 方法里的,因此,只需要在 message_handler 中判断是不是需要调用 test 方法。

class Robot(object):
    def message_handler(self, testcase):
        while True:
            response = self.queue.get()
            handler = self.handler_selector(response[0])
            if response[0] == testcase.get('command'):
                handler.test()
            else:
                handler.work()

3.3.2 结果记录

Robot 类添加一个结果收集列表。

class Robot(object):
    testOutput = list()

将执行结果输出到列表中

testOutput = [
    {
        "command": "store@buy",
        "state": "fail",
        "playerData": self.playerData
    }
]

3.3.3 日志输出

为 Robot 对象添加 logging 方法,将日志输入到文件中

import time

class Robot(object):
    def logging(self, level, msg):
        with open("log.txt", "a") as fp:
            data="{datetime} [{level}] {msg}".format(
                datetime=time.strftime("%Y/%m/%d %H:%M:%S"), 
                level=level, msg=msg)
            fp.write(data+"\n")

3.4 测试报告

大家自行选择合适的展示方式,我倾向于将结果输出到 html 文件中。

3.5 持续集成

使用 linux 自带的 crontab 模块,定时执行测试任务,生成测试报告。

利用 Jenkins,新建触发器 Poll SCM,新建自动化接口测试任务,代码更新后触发自动化测试。

3.6 小结

这种验证方式,理论上适用所有基于 socket 协议的 C/S 应用,大家可以自行尝试。😋

4.拓展应用

4.1 游戏测试场景构建

假如游戏使用了 H2 数据库,这是一种内存数据库。这意味着游戏运行时,你很难直接修改数据库的数据,除非开发人员事先开发了专用的接口。某一个活动需要 2000 人报名,并且每个人都需要通过战斗获取勋章和积分,最后根据勋章和积分排名每个人都有随机的奖励。

对于这样一个测试场景,传统造数据方式:先停服,然后编写 SQL 将数据写入 MySQL,然后启动游戏服,让数据从 MySQL 数据库中读入内存数据库。

如果时使用接口自动化的工具,那么只要开启多进程,发送活动报名接口,再发一些战斗接口,就很轻松地创建了测试场景。既方便了测试,方便了前端开发。

4.2 压力测试

选择单一接口或场景,多进程跑接口,对服务端施加负载。

jvm 运行:使用 jstack,Jprofiler 等工具,

接口响应时间:游戏客户端编写接口响应时间统计模块(思路:接口发送时间和接收时间差,由于服务端存在推送包,数据包的发送后收到的包不一定是响应包)。

cpu、内存占用,psutil 和 matplotlib 绘制性能曲线。

TPS:awk 统计服务端日志

4.3 机器人仿真模拟

给游戏客户端制定一定的行为策略,就是游戏机器人。机器人可以模拟用户的操作,我们可以收集信息,供策划决策。

策划希望研究不同计策对游戏胜负的影响,那么我只要设计场景,游戏机器人带不同计策,记录游戏结果。重复若干场,得到统计数据。策划可以分析数据,调整计策的数值。

比如火攻计策对玩家的伤害过高,不符合策划对于改计策的定位,也影响了玩家的游戏体验,削弱。

我们知道王者荣耀的英雄数值,即使上线后还在调整,如果有了机器人仿真模拟,得到了某英雄太弱,可以提前调整数据,从而避免了把问题带到了线上。

5.作者的话

我一个测试搞了这么多幺蛾子干嘛,好好做功能测试不好吗😆

写这篇文章花了 4 天时间,不知道版主大哥能不能赏脸给个精华贴。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 37 条回复 时间 点赞

我可以看到你实现了一个简单的 socket 客户端,但是用于自动化测试或者压测都过于简陋了。在游戏自动化测试中,你需要处理服务器主动推送的消息,例如同场竞技的其他玩家的操作同步,以短连接的同步通信思路去设计测试框架其应用范围是及其有限的。在压测中,你需要学会引入异步 IO 来增加目前压测工具的并发处理能力,尝试用 gevent 或者其他异步 IO 网络库去实现压测客户端。更重要的是无论是自动化测试或者压测,让通信过程顺利运行起来只是一部分工作。游戏的接口返回值真的可以满足功能验证的要求吗?最后,游戏测试技术落后 5 年并非是所有游戏测试从业者的感受,游戏测试有其特殊的情况存在,引擎技术方案不统一、各大公司间的直接竞争关系导致游戏测试技术很难直接参照和公开交流。但或许只是我的自我感觉,归根结底像是王者荣耀、阴阳师这些游戏的测试技术水平到底是领先还是落后,谁又说的清呢?

我有以下几点需要说明:

  1. 如果是你认为是简单的 socket 客户端,那肯定是没看全。 这个很明显是游戏客户端的量级。包括接收消息的线程 message_collector 和处理消息的线程 message_handler。消息是通过收集消息的线程放在队列Robot.queue中,等待处理消息的线程异步处理的,因此绝不是简单的同步通信。异步消息的数据验证,也是游戏接口自动化测试的难点之一。
  2. 推送的处理方式:自行定义推送的处理器,比如push@store,添加处理方法,然后在 Handler 中注册。 handlers = {"push@store":PushStore} message_collector收到服务端push@store推送时,会把消息数据放到Robot.queue中,等待message_handler处理。
  3. 此外你提到的 gevent 异步 IO 库,在我这里根本用不到,因为本身已经实现了异步处理,理由参考 1,2 两点。
  4. 关于测试的验证,当然不止接口数据验证这一种方式,还可以 pymysql,查询数据库校验。因为篇幅原因,没有写出其中。
  5. 本文我重点讨论的如何进行接口自动化测试,想要做压测需要做额外的优化,这部分优化点我并没有写在文中,如果你感兴趣,我可以另写文章探讨。
  6. 据我所知,游戏大厂有成熟的游戏 UI 自动化框架,这里讲的是接口自动化框架,这两者直接对比先进还是落后是否有失偏颇。另外游戏公司并不是只有腾讯网易,大多数中小厂依然是功能测试为主流,如果这都不算落后,那么什么算先进呢?

以上,欢迎批评指正。

39楼 已删除
  • 这里只是提供思路,代码涉及到公司业务,还不能开源。对于想要的人来说,已经有足够多的信息了。
  • 如果你认为是和 http 的接口测试一样,那我也没办法啊😅
  • 对于 curd 这个,理论上所有东西都在研究如何 curd 和更好的 curd。
  • 测试的确需要分析业务场景写测试用例,不过本文重点介绍的不是这个。
  • 写代码的测试真的搞不清楚业务逻辑吗?

感谢分享~
不过 “不会写代码的测试不能保证软件质量”,有失偏颇。代码也只是工具之一而已。

感谢这么好的分享!
提两点建议:
1、接口测试还有一个部分是安全侧测试,把这个补充上,整个文章更全面一些;
2、最后一部分机器人这个,其实机器人行为还是很难拟真的。根据二八原则我们可以知道,更多的 bug 其实是因为少部分不按套路出牌的玩家行为导致的,这个通过机器人其实很难发现设计是否合理。多年前做端游测试的时候我们也写机器人来模拟,收集数据,后来发现上线后偏差还是较大,这个成本收益比太高,所以渐渐就不做了。另外采取其他方式去解决设计思路的问题。

老马哥有话说:Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
期望楼主为我们放出有亮点的接口自动化测试解决方案。

Ouroboros 回复

我收回那句话。你说的没错,代码也是工具。重要的是质量保证的思想。

redcafe_wei 回复

首先,感谢您的建议,我会不断改进的。
关于游戏机器人,目前局限性的确比较大,期待人工智能的技术的发展,能够实现低成本,高可用的 AI。

Allen.liu 回复

尝试做一个开源通用的游戏接口测试框架,有兴趣的朋友可以找我一起。

聪哥您好,恕我冒昧,我入行以来都是点点点测试,我应该如何提高自己,从哪些方面入手,希望指点一二,谢谢。

往事随风 回复

你好,往事随风。感谢抬爱,不敢说指点,只能是说说我自己的思路。

几个小问题
问自己几个问题:我想成为什么样的人?然后那样的人需要承担什么样的责任?需要什么样的能力?愿不愿意为此付出自己的努力?

激烈的竞争
我刚入行那会,点点点的测试是主流,那时候开发转行测试特别吃香,因为同样是点点点,开发更了解产品是如何实现,所以很多招聘介绍上都写着开发转测试优先。现在测试招人,懂代码早已不是什么值得一提的优势,会自动化测试已经是标配了。总的来说,目前 IT 行业从业人员趋于饱和,竞争非常激烈。如果你不考虑转行的话,你需要别人会得更多,提供的价值更大。

发展的方向
测试水平再高也只是发现问题,未来企业更需要的是质量保证人员,这就需要你有软件开发全流程的质量保证能力,参考文章:《如何保证软件质量》

提升的计划
短期:尝试了解产品的技术栈;在工作中思考如何保证产品质量;学习测试技术;学一种高级编程语言(推荐 python)。
中期:尝试构建质量体系,在工作中不断发展和完善;有一种擅长的编程语言,能自己编写测试工具;

学习 Python,有什么可以练手么,就是看了概念,没有实际操作的项目,没有实战环境

往事随风 回复
  1. requests 接口测试,HTTP 协议的项目都有接口可以测。
  2. scrapy 做爬虫,爬你感兴趣东西
  3. matplotlib 画图, 最近哈工大被禁用 matlab 了,这是一个很好用的替代方案。
  4. flask + mysql 做博客后台,学完之后你就知道后端都要做些什么。

这些网上都有资料可以找,另外,推荐一本书《Flask Web 开发实战》

Django 也可以吧? 谢谢 ,我也是游戏测试一枚,目前还在看 Python 的基础知识。

仅楼主可见
30楼 已删除
仅楼主可见

😀 我知道你在锐战啊,上海的话可以来交流。游戏测试现在很多测试开发,可以走出来看看。
另外一门 python 肯定是不够的。。。

主流都是协议文件用开源转 Json 或者 dict。
python 是可以定义接收数据结构的,另外大部分场景还是放到非 window 上用,比如压测的,block 的 Select 有点慢,可以用 nio 的 epoll。

陈子昂 回复

肯定不止会一门语言啊,python 最拿手,最近在学 go 语言,不能落伍啊。
确实在上海,不知道怎么交流,有线下的交流会吗?

苏立轩 回复

欢迎,qq:1227753320

仅楼主可见

最近在着手搞这一块,有很多想法,在考虑落地。希望能多交流交流

往事随风 回复

取消验证问题了

weixiaovision 回复

欢迎加 QQ 交流

加你了~弄个群吧,

weixiaovision 回复

加 QQ 群交流:1084835439

楼主,我想问一下,你这一套接口测试协议,对于使用 protoBuf 来定义和解析协议的通讯方式有用吗,如果有用的话,能提供点思路吗,感激不尽

我这个相当于是自己规定格式,直接发二进制数据流。protobuf 只不过是 google 自己规定的格式,底层发的也是二进制数据流,你照着它的格式发是没有问题的。

话又说回来,既然 google 已经有了工具,就不要自己重复造轮子了。

做了游戏测试 6,7 年,算是行业比较早的一批游戏测试,后来转了开发,想说 2 句:

  1. 游戏测试技术并不是落后,而是游测入门门槛低,因为起初那个时代行业招的就是黑盒点点点,大家的技术门槛都低,顶多在页游时代 大家会和 web 一样测测 api 接口,但是后来随着游戏的发展。涉及到游戏技术深入门槛提高,开发所涉及的技术也提高了,但是入门的门槛还是那么低,导致测试的技术上手门槛变高了,国内又没有特别大的游戏测试圈子,发展慢是正常的。

  2. 游戏测试做到了深入 就是技术和管理 的侧重方向,并不用较真的去觉得这个行业不行,因为一旦到了那个资历你不是坐到了 最上的管理岗 就是 在技术方面深入很深,如果没有,就要反思下自己是否在这个公司浪费时间,管理岗 侧重人脉,技术岗侧重自身,不管哪个岗位 其实都是有底气在,在去做什么都不用怕被这个行业淘汰。

  3. 如果技术岗做到了深入,代码说明很熟练了(语言不重要,语言只是一种工具,不用纠结用哪种,会用哪种用哪种,熟练了学习其他的语言一样快),如果能看懂自家项目,自动化这类东西不会很复杂,看不懂也没有关系,和研发稍微配合一下 ,让研发配合做一些接口,自己整合做一套框架也不太难,关键是动脑和动手能力,题主的方法和现在大厂做想法的基本一致,在客户端上开一个通道 和外部进行通讯,封装,扩展, 可以做的事情很多,无非是细化这个框架的易用性和通用性,以及扩展更多的功能。强大与否其实还是在自身代码和自己项目有多熟练和深入。 剩下的其他自动化的方案(基于外部,图形坐标一类外挂非插装,内挂的方法)我认为都是算野路子,能用,但是其实并不稳定。

  4. 技术岗其实有挺多分支,比如,安全,渗透,反外挂,自动化,性能,能做到全部的其实并不多,在某个分支达到专家级别的个人觉得已经够用,现在比较热门的就是自动化和性能了,性能算是一个加分项。

  5. 其实还有一个比较重要的一点就是地位,测试在公司的地位能很大程度上决定你能做什么事情,如果发现公司并不是很重视测试,你也无法改变这个状况以及学习到任何对你有利的东西,建议早点离职换一家。游戏测试在国外和国内的地位有点倒置,不过看招聘的行情,其实能看到不少游戏测试要求并不低,说明这个行业的地位其实是在慢慢变高的。

ninety 回复

兄弟看的透彻~

十分赞同你说的竞争这块。
毕竟就算再怎么优秀,unity 等引擎的发展也只是为了更方便的让策划做游戏。但 web 就不一样了,至少像 chrome 这样的浏览器,感觉本身就是一个集大成的工具,不仅能给客户用,也能给研发用。
或许未来游戏行业能做出一些更好的规范或者标准,这样才会有更多优秀的工具出现吧。

用 java 写过游戏的接口测试,做的是一个类似王者荣耀的游戏。其他都挺好实现就是强化这块不固定的逻辑不好处理啊。

一个猎头和我说上海做技术工资最高的就是某家游戏公司的测试总监,年薪 200 万。从 BOSS 直聘来看,上海这边对游戏测试很多都有技术方面的要求并且工资也开得不低 ,广州和深圳那边要求相对较低,工资也给得不高。但不管怎么洗白,测试在国内总体还是一个比较边缘化的职业,位低钱少责任重有过而无功,大家有机会转其他岗位早点转吧,男怕入错行。

陈子昂 来自入职半年多游戏测试新人的迷茫 中提及了此贴 02月27日 15:54
仅楼主可见
特尔斯特 回复

哪家,字节跳动吗。

请问楼主,你的开源版本接口自动化框架做了嘛?

聪哥,接受到的消息怎么样跟用例一一对应起来呀,有时候服务器会发一些跟我们发过去的测试数据无关的回包过来,比如有人从身边经过的广播包,定时活动开启的同步包,或者聊天信息之类的乱七八糟的数据,怎么从中找到跟测试数据有关的回包来做断言

兔子🐰 自动化测试合辑 中提及了此贴 02月21日 17:01
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册