ATX ATX 系列 - 如何测试网易云音乐 (Android 篇)

codeskyblue · 2016年07月15日 · 最后由 Bob 回复于 2018年12月30日 · 2978 次阅读

简介

ATX 是AutomatorX的简称,是一个 Python 库,可以用在手机应用的 UI 自动化上,兼容 Android 和 iOS,吸收众多开源框架所长,有着很高的稳定性。
脚本编写也全部采用 Python 语言,虽说,稍微有点学习成本,但却有着相当高的灵活性。

下面就拿我平常用的最多的软件 “网易云音乐” 为例,介绍如何测试一个 Android 应用。

文档分为 3 个部分

  1. 启动应用
  2. 编写脚本
  3. 生成报告

ATX 的安装这篇文章不做详细介绍,参考其官网的主页一步一步的来就可以了 https://github.com/codeskyblue/AutomatorX

启动应用

这里说的启动应用并不是要你手动去点应用的图标,而是告诉你如何用 python 代码来启动应用,Android 启动应用需要知道被测应用的 package_name,如果已经有 apk 的安装包的话,获取起来其实很简单。(我是直接去网易云音乐的主页上下载的)

比如 apk 的文件名叫 netease-music.apk, 打开命令行,输入

$ python -m atx apkparse netease-music.apk
{ 
  "main_activity": "com.netease.cloudmusic.activity.LoadingActivity", 
  "package_name": "com.netease.cloudmusic" 
}

可以看到 package_name 是 com.netease.cloudmusic, package_name 和 activity 一般都是不变的,记录下来,不用一直去查看。

用一个你最喜欢的编辑器,比如 sublime,新建一个文件叫 test_music.py, 最开始的内容这样写

# coding: utf-8 
import atx 

d = atx.connect() 
print d.start_app('com.netease.cloudmusic', "com.netease.cloudmusic.activity.LoadingActivity")

其中的 d.start_app(...) 就是启动应用的意思,返回值还包含了,启动所话费的时间,这里知道就好了,我们先忽略掉返回值,运行下脚本测试下,看一切是否顺利

编写脚本

这里需要用到 uiautomatorviewer 这个工具,它是 android-sdk 自带的一个查看 UI 图层的工具,其下载地址在https://developer.android.com/studio/index.html
下载解压完后,在 tools 目录下可以找到该软件。

打开软件,App 中所有组件的名字,属性,位置都清晰可见。

以个性推荐这个按钮为例,可以看到它的所有属性

  • text=个性推荐
  • class=android.widget.TextView

把该元素,表示为一个 python 对象为 (这里是重点,我加粗表示)

d(text=u'个性推荐', className='android.widget.TextView')

下面我们开始设计第一个用例,完成的功能就是

  1. 打开网易云音乐 App
  2. 点击个性推荐 -> 进入到每日歌曲推荐
  3. 因为是未登录用户,所以会出现文字 “暂时没有内容” 验证完之后,返回首页

利用 uiautomatorviewer 获取到所有需要点击的元素

  1. d(text=u'个性推荐', className='android.widget.TextView')

  2. d(text=u'每日歌曲推荐')

  3. d(text=u'暂时没有内容')

  4. d(description=u'转到上一层级')

然后组合成一段 python 代码

# coding: utf-8
import atx

d = atx.connect()

def main():
    d(text=u'歌单').click()
    d(text=u'个性推荐').click()
    d(text=u'每日歌曲推荐').click.wait() # 点击并等待页面刷新

    assert d(text=u'暂时没有内容').exists
    print 'Back'
    d(description=u'转到上一层级').click()
    print 'Finish'

if __name__ == '__main__':
    main()

生成报告

脚本写好了,直接用命令行就可以调试了, python test_music.py,一切顺利的话,就可以看到手机按照我们预先定义的操作一步步的在运行了。
现在只要,在继续前进一小步,就可以生成一个不错的测试报告了。我们需要用到 atx 所提供的一个测试报告扩展插件 atx.ext.report.Report

稍微修改代码的前几行,改成

# coding: utf-8
import atx
from atx.ext import report

d = atx.connect()
rp = report.Report(d, save_dir='report')
rp.patch_uiautomator()
rp.info("Start test")


def main():
    d(text=u'歌单').click()
    d(text=u'个性推荐').click()
    d(text=u'每日歌曲推荐').click.wait(timeout=10)

    assert d(text=u'暂时没有内容').exists
    print 'Back'
    d(description=u'转到上一层级').click()
    print 'Finish'

if __name__ == '__main__':
    main()

运行后,在运行脚本的当前目录下就会发现多了一个 report 的目录。用浏览器打开其中的 index.html 就可以看到每一步的操作记录了。

为了方便起见,我传了一张图到外部的云存储上
https://o8oookdsx.qnssl.com/html_reports/atx-cloudmusic-report/index.html

另外也截一张图,方便没有网络不好的同学

到此,文章就算结束了,可以集成到 Jenkins 或者自己建设的平台上。

后记

自动化测试的道路漫长艰辛,但却又前途光明,可能还有一些不足,还有些不完善,但在不断的努力下,所有的问题,都将会逐一攻破。

作者:codeskyblue 2016-07-14 杭州

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 28 条回复 时间 点赞
老马 ubuntu16.04 ATX 使用记录 中提及了此贴 01月25日 17:23
hong111 回复

没了

想问下 blockly 没有了吗

播放某一首歌曲的用例如果写断言判断 pass or failed?

打开 APP 的代码好像没有,怎么判断是要打开哪个 APP?

感谢分享。用 Uiautomatorviewer 获取静态的 native 控件是不错的,但是动态的 UI 下(比如说播放音乐时,屏幕上有进度条之类的动态元素),或导致 Uiautomatorviewer.dump 失败,获取不到元素,怎么处理呢?

#1 楼 @jamesparagon atx 支持通过定位图片的方法,来查找元素的。仔细看看 README,里面有的

不错,什么时候能支持 py3。

#3 楼 @among29 这个暂时没有计划

codeskyblue [该话题已被删除] 中提及了此贴 09月12日 16:28

这个用例执行后怎么判断 PASS 了?

#7 楼 @jojotester 你可以用 assert,或者内置的 assert_exists 函数来判断

网易音乐,经常自动唤醒播放音乐,这事你能管嘛

—— 来自 TesterHome 官方 安卓客户端

#9 楼 @totoro 这个我当然管不了,印象中里面有个反馈通道,你试试那个

#12 楼 @codeskyblue issue 在哪里提 大神 下面是日志


总提示我获取设备列表失败

#11 楼 @yaniray 高端呀,文档我还没写,你都用上了。把控制台的日志记录下,提个 issue

#12 楼 @codeskyblue 刚开始是好使的,启动好使,但是使用取图片的时候,app 总挂,不知道是什么问题

codeskyblue [该话题已被删除] 中提及了此贴 10月26日 15:57

看起来好便捷的样子,对了,为什么获取到 text,还要用 class name

请问:我把截取的图片放到了一个文件夹里面,应该怎么实现点击这张图片

直接填上完整路径
#18 楼 @lwj

atx.ext.report.Report 这个现在是把每一步的记录截图放在 report 这个目录下,没有生成 html 文件了吧

@codeskyblue 目测就生成了一个 image 的文件夹和一个 output.ficache 空文件~~好吧,是我没有生成报告


使用 pip install --upgrade --pre atx 安装 ATX 到最后报错,该工具是否能支持 Python 3.X? 或者是我安装方式不对?有解决办法吗?

bo 回复

谷歌下看看,一般都有解决办法的,支持 py3 的 我手机看的,不太方便

报错如下,找不到问题在哪里了。步骤是刚进入 webview,点击 “立即预约” 按钮,就点不动了。

Traceback (most recent call last):
  File "D:\TestWork\code\UI\caboli.py", line 22, in <module>
    d(description=u"立即预约 Link").click()
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 108, in __call__
    return self.func(*args, **kwargs)
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 77, in _inner
    hook_func(dict(name=fn.__name__, self=instance, args=args, kwargs=kwargs, is_before=True))
  File "C:\Python27\lib\site-packages\atx\ext\report\__init__.py", line 77, in _uia_listener
    self.__uia_last_position = center(evt.this.bounds)
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 890, in __getattr__
    info = self.info
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 901, in info
    return self.jsonrpc.objInfo(self.selector)
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 433, in wrapper
    return _method_obj(*args, **kwargs)
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 203, in __call__
    return self.remote_call(data)
  File "C:\Python27\lib\site-packages\uiautomator\__init__.py", line 190, in remote_call
    "%s: %s" % (jsonresult["error"]["data"]["exceptionTypeName"], jsonresult["error"]["message"])
uiautomator.JsonRPCError: <exception str() failed>
[Finished in 54.9s]
DeX 回复

先把 report 去掉,另外加下 QQ 群,群里问问

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册