前段时间,写了 - atx 对游戏分发包实践,竟然加精了。。还被加入 atx 的索引了。。
现在来个 2.0 主要是整体调整了,不再像 1.0 那傻傻的。一个渠道对应不同的游戏,即系 1--> N。2.0 是渠道和游戏脚本动态的组合,即系 N-->N
1.0 是一张张截图去执行,2.0 是根据截图的操作名称去执行。比如进入游戏的一系列操作,命名会是 ‘enter_game_001’---'enter_game_010'
新手指引 ‘guide_001’---'guide_100'等等。简单来说,就是 利用排序去循环执行。。不知道你们看懂了没有。。哈哈哈哈,我都不知道怎么描述了
methods 是游戏和渠道脚本都继承的类,因此这个类有大量的公共方法
需要划动的是话,调用 swipe() 即可,当然也可以直接调用 up_swipe() 等
def size(self):
if configure.device_name == '':
size = 'adb shell wm size'
else:
size = 'adb -s %s shell wm size' % configure.device_name
a = os.popen(size)
for i in a:
pass
size =i.split(': ')
size = size[1].split('x')
size= [int(size[0]),int(size[1])] #size[0] 为width size[1] 为high
return size
def swipe(self,driver,direction):
if direction == 'up':
return self.up_swipe(driver)
elif direction == 'down':
return self.down_swipe(driver)
elif direction =='right':
return self.right_swipe(driver)
elif direction == 'left':
return self.left_swipe(driver)
else:
print '没传滑动方向,不做滑动操作,up,down,right,left'
def up_swipe(self,driver):
size = self.size()
driver.swipe(size[0] /2, size[1] *0.8, size[0] /2, size[1] *0.2, steps=10)
sleep(1)
def down_swipe(self,driver):
size = self.size()
driver.swipe(size[0] / 2, size[1] * 0.2, size[0] / 2, size[1] * 0.8, steps=10)
sleep(1)
def right_swipe(self,driver):
size = self.size()
driver.swipe(size[0] *0.2, size[1] /2, size[0] *0.8, size[1] /2, steps=10)
sleep(1)
def left_swipe(self,driver):
size = self.size()
driver.swipe(size[0] *0.8, size[1] /2, size[0] *0.2, size[1] /2, steps=10)
sleep(1)
下面的方法,无论是什么图片操作,都需要用到这个方法。
def get_name(self,name,way_name='game'):
'''
通过os.listdir 去获取文件夹所有截图,通过 re.match,获取所需要的截图名称
:param name: 截图名称的前缀 如 name == 'pay_in'
:param way_name: 区分游戏截图还是渠道截图
:return: 返回一个有截图名称的list,如 ['pay_in_01','pay_in_02'......]
'''
if way_name == 'game':
path = './/'+way_name+'/'+configure.game_name+'_images'
else:
path = './/' + way_name + '/' + configure.channel_name + '_images'
a = os.listdir(os.getcwd() + os.sep + path)
b = []
name = '%s.*'%name
for i in a:
logo = re.match(name, i, re.M | re.I)
if logo:
logo=logo.group().split('.') #截图名称格式一般是这样enter_game_01.1920x1080.png
b.append(logo[0]) #分割后,获取的是 enter_game_01
b = list(set(b)) #去重
b = sorted(b) #排序
return b
有 2 个,一个是判断是否需要过指引,一个是判断是否进入到正确的第三方支付
def guide_exist(self,driver,name):
'''
判断目标图片是否存在,该方法主要判断 游戏引导第一个图片
:param driver:
:param name: 目标截图前缀
:return: 目标图存在则返回非空,不存在则返回 None
'''
global image
name = self.get_name(name)
for x in xrange(10):
print '第 %s 次寻找: %s' % (x + 1, name[0])
image = self.images_or_none(driver, name[0] + '@auto.png')
if image:
print '引导图片存在,需要过引导: ' ,name[0] ,image
break
if x == 9:
print '引导图片不存在,不需要过剧情: ',name[0],image
return image
def pic_exist(self,driver,name,way_name):
'''
支付操作第三步,判断图片是否存在
该方法,主要是判断,第三方支付界面的图片
判断当前界面是相应的第三方支付界面
:param driver:
:param name: 目标图片
:param way_name: 区分游戏和渠道截图的路径
:return: 图片存在,返回非空,不存在 返回None
'''
name = name[0].replace('in_01', 'exist')
name = self.get_name(name, way_name)
for i in xrange(5):
print strftime('%Y-%m-%d-%H-%M-%S') + '第 %s 次寻找: %s' % (i + 1, name[0])
image = self.images_or_none(driver, name[0] + '@auto.png', way_name)
if image:
print(strftime('%Y-%m-%d-%H-%M-%S') + '--查找*******图片 %s 成功---图片信息 %s' % (name[0], image))
return image
if i == 4:
return None
介绍 2 种方法,一种是找不到图片会 return None(game_click()),一种是找不到当前图片,会继续找下一张(game_pay())
def game_click(self,driver,name):
'''
寻找和点击所有目标图片,如 目标图片是 guide_001 -----guide_100,只需 name 传入 'guide' 就会寻找和点击这些图片
:param driver:
:param name: 目标图片的前缀
:return: 所有图片都找到和点击,返回一个非空,如果某张图片达到循环最大值都没找到,则返回 None
'''
name = self.get_name(name)
for i in name:
for x in xrange(10):
print (strftime('%Y-%m-%d-%H-%M-%S')+'第 %s 次寻找: %s' %(x+1,i))
image = self.images_or_none(driver,i+'@auto.png')
if image:
sleep(2)
driver.click(image[0][0],image[0][1])
#self.click_images(driver,i+'@auto.png')
print (strftime('%Y-%m-%d-%H-%M-%S')+'--点击图片 %s 成功---图片信息 %s' %(i,image))
break
if x == 9:
print '无法匹配到图片:', i
return image
return 'ok'
def game_pay(self,driver,name):
'''
调起渠道支付界面的方法,先判断 activity,如果当前的activity是渠道支付界面的,则不再做操作,
如果不是,则寻找和点击目标图片,目标图片不存在,则跳过,继续操作下一张图片.
:param driver:
:param name: m目标截图名称
:return: 如果循环,达到最大次数,返回None
'''
name = self.get_name(name)
for x in xrange(10):
if self.get_view_info(driver) == self.get_channel():
print unicode('已经进入到支付界面')
return 'ok'
else:
for i in name:
print (strftime('%Y-%m-%d-%H-%M-%S')+'寻找: %s' % (i))
image = self.images_or_none(driver, i + '@auto.png')
if image:
sleep(1)
driver.click(image[0][0], image[0][1])
print(strftime('%Y-%m-%d-%H-%M-%S') + '--点击图片 %s 成功---图片信息 %s' % (i, image))
if x == 9:
print unicode('进入支付界面失败')
return None
支付流程大概如下:选择第三方支付方式--->点击一个调起第三方支付的按钮--->到达第三方支付界面--->退出第三方支付界面
现在的方法对应是 : pay_in--->pay_up--->判断第三方支付界面---> pay_out
判断第三方支付界面有 2 种方式,一种是上述说到的 pic_exist(),判断第三方支付的图片,另一种就是 判断当前的 activity 或者 package
def pay_in(self,driver,name,way_name='channel',direction=None):
'''
支付界面第一步操作,找到相应的支付方式
:param driver:
:param name:目标截图名称
:param way_name: 区分游戏和渠道截图的路径
:param direction: 如果图片,是否需要滑动操作,如需要则传入 'up' 'down' 'right' 'left',不需要就是None
:return:
'''
name = self.get_name(name, way_name)
for i in name:
for x in xrange(5):
print strftime('%Y-%m-%d-%H-%M-%S') + '第 %s 次寻找: %s' % (x + 1, i)
image = self.images_or_none(driver, i + '@auto.png', way_name)
if image:
driver.click(image[0][0], image[0][1])
print(strftime('%Y-%m-%d-%H-%M-%S') + '--点击图片 %s 成功---图片信息 %s' % (i, image))
break
else:
self.swipe(driver, direction)
def pay_up(self,driver,way_name):
'''
支付界面第二步操作,找到发起支付的按钮,如‘立即支付’ '确认支付'
:param driver:
:param way_name: 区分游戏和渠道截图的路径
:return:
'''
name = self.get_name('pay_up', way_name)
for i in xrange(5):
print strftime('%Y-%m-%d-%H-%M-%S') + '第 %s 次寻找: %s' % (i + 1, name[0])
image = self.images_or_none(driver, name[0] + '@auto.png', way_name)
if image:
driver.click(image[0][0], image[0][1])
print(strftime('%Y-%m-%d-%H-%M-%S') + '--点击图片 %s 成功---图片信息 %s' % (name[0], image))
break
def pay_out(self,driver,name,way_name='channel'):
'''
支付操作第四部 退出支付界面,不能直接BACK键退出的,需要用图片退出才用该方法
:param driver:
:param name: 目标截图
:param way_name: 区分游戏和渠道截图的路径
:return:
'''
name = self.get_name(name, way_name)
for i in name:
for x in xrange(5):
print strftime('%Y-%m-%d-%H-%M-%S') + '第 %s 次寻找: %s' % (x + 1, i)
image = self.images_or_none(driver,i+'@auto.png',way_name)
if image:
driver.click(image[0][0], image[0][1])
print(strftime('%Y-%m-%d-%H-%M-%S') + '--点击图片 %s 成功---图片信息 %s' % (i, image))
break
def get_view_info(self,driver,act_or_package=1):
'''
获取当前界面的 packages,activity
:param driver:
:param act_or_package: 0 是package 1 是activity 2是 PID
:return:
'''
sleep(2)
return driver.current_app()[act_or_package]
def pay_exist_pic(self,driver,name,way_name='channel',direction=None):
'''
其实就是 pay_in pay_up 和 pic_exist 的调用。。。
使用:判断是否进入到相应的第三方支付界面,通过 图片判断,
:param driver:
:param name: 目标图片
:param way_name: 区分游戏和渠道截图的路径
:param direction: 是否滑动
:return: pic_exist
'''
self.pay_in(driver,name,way_name,direction)
self.pay_up(driver,way_name)
return self.pic_exist(driver,name,way_name)
def pay_exist_act(self,driver,name,act_or_packages = 1,way_name='channel',direction=None):
'''
其实就是 pay_in pay_up 和 get_view_info 的调用。。。
使用:判断是否进入到相应的第三方支付界面,通过 activitv或者 package 判断
:param driver:
:param name: 目标图片
:param act_or_packages: 0 是package 1 是activity 2是 PID
:param way_name: 区分游戏和渠道截图的路径
:param direction: 是否滑动
:return: get_view_info
'''
self.pay_in(driver,name,way_name,direction)
self.pay_up(driver,way_name)
sleep(10)
return self.get_view_info(driver,act_or_packages)
这里主要介绍 支付的 pay_exist_act() 和 pay_exist_pic() 具体使用
def wechat(self,driver):
if self.pay_exist_act(driver,'wechat_in',0) == wechat: #判断微信的package naem
for i in xrange(2):
driver.keyevent('BACK') # 按2次back 键
self.pay_out(driver,'wechat_out') # 渠道支付界面退出
if self.get_view_info(driver) != channel_pay_activity: #判断是否退出成功
return 'ok'
else:
return None
else:
return None
def China_Mobile(self,driver):
if self.pay_exist_pic(driver, 'China_Mobile_in'): # 判断第三方支付界面
driver.keyevent('BACK') # 退出支付界面
if self.get_view_info(driver) != channel_pay_activity: #判断是否退出成功
return 'ok'
else:
return None
else:
return None
游戏脚本内容比较少,一个就是进入游戏,一个调起支付
def enter_game(self, driver):
'''进入游戏,有引导过引导'''
self.game_click(driver,'enter_game_01') #点击进入游戏
sleep(10)
if self.guide_exist(driver,'guide_001'): #判断是否需要过指引
result = self.game_click(driver, 'guide') #过指引
return result
else:
result = self.game_click(driver, 'enter_game_02') #不需要过指引的操作
return result
def game_pay_up(self, driver):
'''调起支付界面'''
result = self.game_pay(driver, 'pay')
return result
channel_name = 'sdk2345'
game_name = 'hhw'
device_name = '2aa530ef'
package_name = 'xxxxx'
activity_name = 'com.platform.main.MainActivity'
account = 'zhaotest8' #登录账号
password = '123456' #登录密码
class Get_name(object):
'''
根据configure 配置的游戏名和渠道名,返回包含上一层级的路径
为动态 import 提供 str
'''
def get_game(self):
if configure.game_name =='hhw':
return 'game.hhw'
elif configure.game_name == '':
return 'game.xx'
else:
print unicode('该游戏没有脚本')
exit()
def get_channel(self):
if configure.channel_name == 'sdk2345':
return 'channel.sdk2345'
elif configure.channel_name == '':
return 'channel.xx'
else:
print unicode('该渠道没有脚本')
exit()
def get_names(self,name):
'''
动态import 游戏和渠道相应的测试类
:param name: 动态import 游戏还是 渠道
:return: 返回 游戏 或者 渠道 实例 的类
'''
import public.get_names as get_names
get_names = get_names.Get_name()
if name =='game':
game = __import__(get_names.get_game())
game_name = get_names.get_game().split('.')[1]
game = getattr(game, game_name)
game = game.Game()
return game
if name == 'channel':
channel = __import__(get_names.get_channel())
channel_name = get_names.get_channel().split('.')[1]
channel = getattr(channel, channel_name)
channel = channel.Channel()
return channel
game = self.get_names('game')
channel = self.get_names('channel')
channel.login(self.driver)
game.enter_game(self.driver)
channel.wechat(self.driver)
开始部分:是 更新,公告,登录,判断是否需要过引导,以及引导的操作
这部分:是 引导结束,转到 支付流程,和第三方支付的操作
这部分:最后一个第三方支付执行完成,测试结束