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

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

简介

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 条回复 时间 点赞

感谢分享。用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 这个我当然管不了,印象中里面有个反馈通道,你试试那个


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

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

#12楼 @codeskyblue 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群,群里问问

小马 ubuntu16.04 ATX 使用记录 中提及了此贴 01月25日 17:23

想问下blockly没有了吗

hong111 回复

没了

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

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

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