首先感谢网易的各位大神,从 ATX 到 Airtest 收获颇多
在手游中,一般新手指引都是固定的强制步骤,所以我们可以用自动点击的方式直接跑完整个新手
以上三种方法,在编写测试代码的时候都需要手动跑至少一遍新手测试
坐标的话,需要测量计算
图片的话,主要的工作量在截图
UI 对象的话,只需要测需要的 UI 就可以了(可能并不需要手动跑完整个新手)
对比下来,UI 的工作量是最小的;而且以上三种方法可以结合使用
而且使用 UI 对象有个最大的优势,可以取到游戏内的文本,可以进行更复杂的逻辑操作
学 ATX 时写的基于图片操作,完全写死的步骤
# -*- encoding: utf-8 -*-
import atx
from atx.ext.report import Report # report lib
import time
game_name = u"xxx" 隐藏了
device_name = u"84B7N16620000490"
package_name = u"xxxxx" 隐藏了
activity_name = u"xxxxx" 隐藏了
pic_url = u"C:\\Users\\HBoPRC\\xxx\\"
d = atx.connect(device_name)
rp = Report(d, save_dir = pic_url + "Report\\")
rp.patch_uiautomator() # for android UI test record (optional)
rp.info(u"Test started")
d.click_image(pic_url + 'queding@auto.png')
time.sleep(2)
......省略
#关闭队伍界面
d.click_image(pic_url + 'zy_180@auto.png', offset = (1, -0.5), safe = False)
time.sleep(2)
#一段对话
d.click(0.5, 0.5)
time.sleep(3)
#点击前往挑战
d.click_image(pic_url + 'zy_0@auto.png', offset = (-1.5, -1), safe = False)
time.sleep(5)
#停止指引
d.click(0.5, 0.5)
rp.close()
这段代码中,详细列举了新手的每一步操作,搜索图片,然后点击对应的位置
因为代码中所写的步骤都是固定的,所以面临两个问题
引导修改
如果游戏迭代过程中,对新手指引的步骤进行了修改,代码也需要同步修改
中断
如果代码执行过程中断了,继续执行的话,需要删减部分代码
如果游戏内出现阻碍新手的弹框、提示之类的,也无法进行判断
所以我们需要一个更好的办法来解决通用和中断的问题
部分资料
Python 基础:http://www.runoob.com/python3/python3-tutorial.html
Poco 文档:http://poco.readthedocs.io/zh_CN/latest/
Poco 示例:http://poco.readthedocs.io/zh_CN/latest/source/README.html#tutorials-and-examples
接下来的过程以另一个游戏为例,使用基于 UI 的方式来执行新手指引的过程
这里需要提前集成 Poco-SDK
我们先分析下整个新手过程中的通用部分,我们主要是把整个新手拆分成不同的 UI,方便我们进行不同的操作
有了大致的 UI 后,我们可以考虑直接使用循环点击指引手指指引的位置,过程中存在其它界面时,就执行对应的操作,大致结构如下:
while(true):
if 指引手指.exists():
点击手指位置
elif 剧情对话.exists():
点击剧情对话
elif 其他界面.exists():
点击界面位置
上面的代码就不需要和最初那样,考虑新手指引的步骤;因为一直在检查当前界面显示的 UI,所以也不用考虑执行中断后重哪里继续
但是游戏过程中需要考虑到一个问题,在网络中断的时候,弹框会和指引手指或者其它界面一起出现;虽然其它 UI 会被提示框遮挡,但是 UI 还是存在于当前界面的;所以在判断的时候,需要考虑下编写的顺序
在 Poco 的示例中有一个等待 UI 出现的方法
在超时前返回等到的第一个 UI 代理对象,等不到 UI 时会报错
所以上面的代码可以改一下:
while(true):
ui = poco.wait_for_any([指引手指,剧情对话,其他界面])
if ui is 指引手指:
点击手指位置
elif ui is 剧情对话:
点击剧情对话
elif ui is 其他界面:
点击界面位置
但是在等待过程中,一直没有找到 UI 时,会报错,我们可以在报错的时候做一些处理,比如停止循环
while(true):
try:
ui = poco.wait_for_any([指引手指,剧情对话,其他界面])
except:
break
if ui is 指引手指:
点击手指位置
elif ui is 剧情对话:
点击剧情对话
elif ui is 其他界面:
点击界面位置
最终使用 Poco 跑新手流程的完整代码
# -*- encoding=utf8 -*-
__author__ = "HBoPRC"
from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco
# 连接设备
connect_device("Android:///")
# 初始化poco
poco = UnityPoco()
# 定义一个变量来判断是否还在新手阶段
isGuide = True
while (isGuide):
# 每次需要重新获取各个界面,以保证取到最新的信息
# 剧情对话界面
talkV = poco("剧情对话")
# loading界面,这里主要是进出战斗耗时比较长,单独列出来
loadW = poco("loading")
# 创建界面
roleS = poco("角色创建")
# 指引手指
finger = poco("指引手指")
# 获得奖励界面,因为有战斗,结算界面没有手指,需要单独处理
getA = poco("奖励界面")
# 各类提示框,主要是断线那部分弹框
popWin = poco("提示框")
try:
# 等待出现上面的界面,设置120s超时,默认就是120s,可以按实际情况修改
# 这里写UI参数的时候需要注意下先后顺序,因为常见的情况:指引的时候可能会断线重连,弹出提示框,此时会同时存在指引手指和提示框,需要先处理提示框
guideV = poco.wait_for_any([popWin, talkV, loadW, roleS, country, getA, finger], timeout = 120)
except:
# 没找到上面的界面,设置不在新手阶段,跳出循环
isGuide = False
break
# 判断,根据出现的界面进行相关的操作
if guideV is popWin:
# 因为提示框的层级最高,我们需要优先判断处理,因为主要是考虑的断线重连情况,这里可以加一个休眠,保证跳过连接过程;或者是再单独判断一个转圈的UI
elif guideV is talkV:
# 如果是对话框,点击关闭
elif guideV is loadW:
# 这里单独处理loading是因为考虑到进入副本战斗的时候,loading过了,还需要先战斗一段时间才会进行指引提示;其实也可以把wait方法里的超时设长点
elif guideV is roleS:
# 角色创建界面,进行选择头像,性别,姓名之类的操作
elif (guideV is getA):
# 这里关闭掉结算奖励界面
elif guideV is finger:
# 指引手指,点击对应的位置就行了
完成以上步骤后,我们已经可以运行一个完整的新手流程了
接下来可以使用命令直接运行写好的 .air 脚本
http://airtest.readthedocs.io/zh_CN/latest/README_MORE.html#run-test-case
将命令保存为不同的批处理文件后,批量打开,就可以做到最简单的多台机器同时运行了,需要注意,如果使用命令的话,需要将脚本内连接设备的代码删掉
python -m airtest run xinshou.air --device Android://127.0.0.1:5037/手机序列号 --log \log\nexus4
python -m airtest report xinshou.air --log_root \log\nexus4 --outfile \log\nexus4\log.html --lang zh
pause