51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 3254|回复: 3
打印 上一主题 下一主题

[转贴] atx 对游戏分发包实践

[复制链接]
  • TA的每日心情
    无聊
    2024-7-12 13:16
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    跳转到指定楼层
    1#
    发表于 2017-6-20 09:57:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 乐哈哈yoyo 于 2017-6-20 10:26 编辑

    我的情况很早之前就看到atx的开源,因为基于图片识别,所以眼前一亮,特别是进入游戏行业后(发行公司,勉强算游戏行业吧。。。。),因为游戏的UI控件,用uiautomator viewer是无法查看的,也就是说,游戏与appium,macaca等基本无缘。。之前用appium把 联运sdk(iOS,Android)的脚本都写好了。脚本中,对游戏内容的操作。。都是坐标点击。



    都是sdk内容case,对支付因为需要进入到游戏里,还要新手剧情等等。所以都是人工测支付。废话不多说了。
    最近上线的游戏有几个。游戏分包后(最少都20+的渠道。。 )所以需要时间比较多,总监说,能自动化的都自动化吧。。然后就开始了(当然也看过其他开源的东东,比如腾讯那个GAutomator,testin的cocos-plugin,但都是需要cp接入的。不适合)
    开始搞起恩,atx环境的东东就不多说了。遇到坑就爬吧!


    点击公告


    点击微信logo自动登录
    然后进入游戏
    点击砖石
    点击6元的
    然后弹出ysdk的支付界面
    这里界面可以用 控件去操作了。点击微信支付,弹出微信支付界面
    这里原生控件无法识别,所以就断言该图片是否为空
    取消支付,这里选择点击返回键,回到 ysdk的支付界面,断言 ‘确认支付方式’的text.
    case 结束。报告如下

    关于并行貌似atx并行好容易,不需要设置端口什么的了。如我的项目结构,安装不同的渠道包后,然后就进入不同的渠道项目,配置好信息,Python  runcase.py就可以了
    经验1,对于无法识别的元素控件,如果使用图片操作的话,尽量不要 截文字的图,因为在不同的rom,虽说都是 标准字体,但也是不一样的,造成脚本兼容性问题
    2,atx 识别控件的话,建议使用 class name 和id,text 不一定能识别到
    1. <pre class="highlight python"><code><span class="n">b</span> <span class="o">=</span> <span class="p">[]</span>
    2. <span class="n">a</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">element</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">driver</span><span class="p">,</span><span class="s">'className'</span><span class="p">,</span><span class="s">'android.widget.TextView'</span><span class="p">)</span>
    3. <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)):</span>
    4.     <span class="n">b</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
    5. <span class="n">a</span><span class="p">[</span><span class="n">b</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s">u'Q币'</span><span class="p">)]</span><span class="o">.</span><span class="n">click</span><span class="p">()</span></code></pre>
    复制代码
    上面的ysdk 支付界面, Q币用text无法识别,但driver.source() 显示的 text就是 Q币。而且那几个支付方式排序是会变的。因此无法直接使用索引值。最后使用这段代码。
    3,还是元素问题,使用appium习惯了,总是用uiautomator viewer 查看元素,但uiautomator viewer 能显示的元素(非webview),atx不一定能识别。出现这种问题时
    多使用 driver.source() 打印一下。
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    该用户从未签到

    2#
    发表于 2017-6-20 10:04:21 | 只看该作者
    18条case跑了21分钟,效率还是偏低了些
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    3#
    发表于 2017-6-20 10:09:23 | 只看该作者
    草帽路飞UU 发表于 2017-6-20 10:04
    18条case跑了21分钟,效率还是偏低了些

    因为要过新手剧情,剧情时间太长,已经向cp提需求,增加跳过剧情
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2024-7-12 13:16
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    4#
     楼主| 发表于 2017-6-20 10:25:06 | 只看该作者
    1. 这个是我的项目结构图,说明一下
    2. run_case.py

    3. run_case.py 是跑脚本得,配置好test case 路径去搜索 py文件,然后把test case加入到测试容器

    4. casepath = './/'+configure.game_name+'_TestCase'
    5. discover = unittest.defaultTestLoader.discover(casepath, pattern='test0*', top_level_dir=None)

    6. result 文件夹与 tmcs_images

    7. result 文件夹是存放测试报告与截图的
    8. tmcs_images 与 tmcs_TestCase 都是存放 图片的,为什么会有两个?。。一个是tmcs_TestCase 做unittest图片相对路径,一个runcase.py的相对路径
    9. configure.py

    10. configure.py 是配置信息的,game_name 是用来区分游戏的。主要作用是 在于 图片存放的路径和 搜索case的路径

    11. game_name = 'tmcs'
    12. device_name = '4c14b8b2'
    13. package_name = 'com.tencent.tmgp.shardsofdestiny'
    14. activity_name = 'com.zhankaigame.destiny.RenWanTangMainActivity'

    15. public.methods.py

    16. public.methods.py 是一些公共的方法,比如获取屏幕像素,断言方法(失败截图),查找元素等,图片操作等

    17. def size(self):
    18.     if configure.device_name == '':
    19.         size = 'adb shell wm size'
    20.     else:
    21.         size = 'adb -s %s shell wm size' % configure.device_name
    22.     a =  os.popen(size)
    23.     for i in a:
    24.         pass
    25.     size =i.split(': ')
    26.     size = size[1].split('x')
    27.     size= [int(size[0]),int(size[1])] #size[0] 为width size[1] 为high
    28.     return size

    29. def dy(self,driver,value1,value2,screen_name):
    30.     self.driver = driver
    31.     try:
    32.         self.assertEqual(value1, value2)
    33.     except:
    34.         self.screencap(self.driver,name=screen_name)
    35.         self.assertEqual(value1, value2)
    36. def dy_IsNone(self,driver,obj,screen_name):
    37.     self.driver = driver
    38.     try:
    39.         self.assertIsNone(obj)
    40.     except:
    41.         self.screencap(self.driver,name=screen_name)
    42.         self.assertIsNone(obj)
    43. def dy_IsNotNone(self,driver,obj,screen_name):
    44.     self.driver = driver
    45.     try:
    46.         self.assertIsNotNone(obj)
    47.     except:
    48.         self.screencap(self.driver,name=screen_name)
    49.         self.assertIsNotNone(obj)

    50. def element(self, driver, methods, value):
    51.     '''
    52.     :param driver:驱动
    53.     :param methods: 方式
    54.     :param value: 值
    55.     :return: 返回对象
    56.     '''
    57.     self.driver = driver
    58.     if methods == 'text':
    59.         return self.driver(text=value)
    60.     elif methods == 'xpath':
    61.         return self.driver(xpath=value)
    62.     elif methods == 'resourceId':
    63.         return self.driver(resourceId=value)
    64.     elif methods == 'className':
    65.         return self.driver(className = value)

    66. def element_or_none(self, driver, methods, value):
    67.     '''
    68.     :param driver:驱动
    69.     :param methods:方式
    70.     :param value:知
    71.     :return:元素存在返回元素,不存在,返回None
    72.     '''
    73.     self.driver = driver
    74.     try:
    75.         element = self.element(self.driver, methods, value)
    76.         if len(element) == 0:
    77.             self.assertEqual(True, False)
    78.     except:
    79.         element = None
    80.     return element

    81. 因为atx 查找元素后,是一个list,如果list为空,也不报错的。。因此写了个方法,return None,主要用来做断言的

    82. def images_or_none(self,driver,images_name,timeout = 10):
    83.     self.driver = driver
    84.     game_name = configure.game_name
    85.     try:
    86.         self.wait_images(self.driver, images_name,timeout)
    87.     except:
    88.         pass
    89.     images =  self.driver.exists('./'+game_name+'_images/'+images_name)
    90.     return images

    91. 这里用到 driver.wait() 和 driver.exists() 这里的图片相对路径,如果图片不存在,return None,主要用来做断言的

    92. def click_images(self, driver,  images_name):
    93.     self.driver = driver
    94.     game_name = configure.game_name
    95.     images = self.driver.click_image('./' + game_name +'_images/'+ images_name)
    96.     return images

    97. def wait_images(self,driver,images,timeout = 10):
    98.     self.driver = driver
    99.     game_name = configure.game_name
    100.     images= self.driver.wait('./' + game_name + '_images/' + images,timeout)
    101.     return images

    102. 这里两个,等待图片出现,一个是 点击图片

    103. def tap(self,driver,value):
    104.     self.driver = driver
    105.     size = self.size()
    106.     return self.driver.click(size[0] * value[0], size[1] * value[1])

    107. 点击坐标的方法,比例点击
    108. testcase

    109. case如下

    110. class YSDKSDK(unittest.TestCase,public.Methods):
    111.     u'''YSDKC-sdk测试'''
    112.     def setUp(self):
    113.         if configure.device_name == '':
    114.             self.driver = atx.connect()
    115.         else:
    116.             self.driver = atx.connect(configure.device_name)
    117.         self.driver.start_app(configure.package_name,configure.activity_name)
    118.         sleep(25)
    119.     def tearDown(self):
    120.         pass
    121.         self.driver.stop_app(configure.package_name)
    122.     def test_013(self):
    123.         u'''调起微信支付,并取消'''
    124.         self.click_images(self.driver, 'game-gonggao@auto.png')
    125.         self.click_images(self.driver, 'game-weixin-login@auto.png')
    126.         sleep(5)
    127.         self.enter_game(self.driver)
    128.         self.pay(self.driver)
    129.         self.element(self.driver,'text','微信支付').click()
    130.         images = self.images_or_none(self.driver,'weixinpay-view@auto.png',timeout=20)
    131.         self.dy_IsNotNone(self.driver,images,'test_013')
    132.         sleep(5)
    133.         self.driver.keyevent('KEYCODE_BACK')
    134.         sleep(5)
    135.         ysdk_pay = self.element(self.driver, 'text', '确认支付方式')
    136.         self.dy(self.driver, unicode(ysdk_pay.text), u'确认支付方式', 'test_013')
    复制代码
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-9-21 08:39 , Processed in 0.071269 second(s), 22 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表