ATX 使用 Python 库 facebook-wda 完成网易云音乐 iOS 客户端的自动化测试 (示例)

codeskyblue · 2017年08月29日 · 最后由 zzr 回复于 2021年10月13日 · 9560 次阅读
本帖已被设为精华帖!

简介

facebook-wda 是ATX项目下面的一个子库,专门提供 iOS 应用的自动化测试,可以通过 ATX 使用这个库,当然也可以单独拿来使用。

这篇文章介绍了如何用facebook-wda这个 python 库来完成一个普通 App 应用的测试,希望通过这个篇文章,能让 iOS 的测试或开发人员,更方便的回归测试自己的应用。开发出质量更高的应用。

选用 网易云音乐 作为被测应用,纯粹是因为我平常用网易云音乐听歌比较多,比较喜欢这款应用

facebook-wda 简要说明

facebook-wda 这个 Python 库,通过直接构造 HTTP 请求直接跟WebDriverAgent通信。它是一个非常短小精悍的一个库,并不像 appium、macaca 还有一个中间转发服务,支持这么多的语言。用它做测试,Python 你必须要会
虽然代码比较精炼,但是能完成的功能却非常强大。你能在 appium 里面找到的功能,这个库有提供,找不到的功能,这个库也有提供。

安装准备

在写代码之后,你需要把下面列的东西都准备好。

  1. 部署 WebDriverAgent https://testerhome.com/topics/7220

    成功安装后,浏览器访问 http://localhost:8100/status会看到一个 json 字符串

  2. 安装 Python 库(目前这个版本的库支持 py2.7~3.5 之间的版本)

    pip install --pre facebook-wda
    

小试牛刀:完成网易云音乐的自动登陆

手机上先安装上一个网易云音乐

通过ideviceinstaller -l 或者其他工具查找到网易云音乐的 bundleId com.netease.cloudmusic

网易帐号我先用两个静态变量代替 USERNAME, PASSWORD

先贴一段代码,看注释理解的比较快一些

首先是设备连接和弹窗处理

import wda

bundle_id = 'com.netease.cloudmusic'

c = wda.Client('http://localhost:8100') # DEVICE_URL

s = c.session(bundle_id) # 启动应用

# 处理不知何时就会突然弹出的警告框
def alert_callback(session):
    btns = set([u'不再提醒', 'OK', u'知道了', 'Allow', u'允许']).intersection(session.alert.buttons())
    if len(btns) == 0:
        raise RuntimeError("Alert can not handled, buttons: " + ', '.join(session.alert.buttons()))
    session.alert.click(list(btns)[0])

s.set_alert_callback(alert_callback)

变量s就代表 wda 的 Session 了,下面通过获取到的 Session 去完成登录

def netease_login(s):
    # 已经登录直接跳过
    # 开头有2s的广告,所以这里需要等待3s
    if s(name=u'发现音乐', type='Button').wait(3, raise_error=False):
        # Already logged in
        return
    # 点击邮箱登录,输入帐号密码,验证是否登录成功
    s(name=u'网易邮箱').tap()
    s(type='TextField').set_text(USERNAME+'\n')
    s(type='SecureTextField').set_text(PASSWORD+'\n')
    s(name=u'开启云音乐').click_exists(timeout=3.0)
    assert s(name=u'发现音乐', type='Button').wait(5.0) # 等待5s

netease_login(s)

使用 python 单测框架 pytest 来组织测试脚本

最近用了用 pytest,感觉比 python 自带的 unittest 好用的不少。安装方法 pip install pytest

直接上脚本 (为了节省篇幅,我就省略了比较常见的 import,包括上面的那个 alert_callback,实际写代码的时候你应该加上去)

def setup_function():
    # 每次测试之前,保证帐号是登录的
    s = c.session(bundle_id)
    netease_login(s)

def teardown_function():
    s.close() # 一次测试结束,关闭应用

def test_discover_music():
    """
    测试 发现音乐->私人FM 中的播放功能
    """
    s(name=u'发现音乐', type='Button').tap() # 默认会寻找10s,所以不用担心点不到
    assert s(name=u'听歌识曲', visible=True).wait()
    s(name=u'私人FM').tap()
    assert s(name=u'不再播放').exists
    assert s(name=u'添加到我喜欢的音乐').exists
    assert s(name=u'00:00', className='StaticText').exists
    s(nameMatches=u'(暂停|播放)').tap() # 点击播放后,按钮会变成暂停,这里用正则匹配下
    assert s(name=u'00:00', className='StaticText').wait_gone(10.0) # 等待音乐播放,进度条开始走了

def test_my_music():
    """
    测试 我的音乐->本地音乐
    """
    s(name=u'我的音乐', type='Button').tap()
    assert s(name=u'最近播放').wait(2.0)
    s(name=u'本地音乐').tap()
    assert s(name=u'管理').wait()
    s(name=u'播放全部').tap()

保存文件为 test_cloudmusic.py,然后命令行运行测试

$ py.test -vv
============================= test session starts =============================
platform win32 -- Python 2.7.13, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 -- c:\python27\python.exe
cachedir: ..\.cache
rootdir: D:\Workdir\facebook-wda, inifile:
collected 2 items

com.netease.cloudmusic\test_discover_music.py::test_discover_music PASSED
com.netease.cloudmusic\test_discover_music.py::test_my_music PASSED

========================== 2 passed in 23.19 seconds ==========================

pytest 会保证调用函数test_discover_music之前把setup_function调用了,在测试结束后把teardown_function调用一次。

通过这种方式可以增加更多的测试。完整示例可以再该地址查看到https://github.com/openatx/facebook-wda/tree/master/examples/com.netease.cloudmusic

PS: 该项目自身的自测代码用的也是 pytest

进一步阅读:控件定位

通过访问 http://localhost:8100/inspector可以获取应用的 UI 图层结构,方便写脚本
比如我们访问到一个控件的属性

直接看着就可以写出代码 s(name=u'听歌识曲', className='Button').tap()

除了这些简单的定位方法还有茫茫多的定位方法。具体查看项目的主页 https://github.com/openatx/facebook-wda 想锻炼下手部肌肉的,还可以顺便点个 Star

结束语

这是一个功能完善且代码很鲁棒的库,不好好推广它,实在是对不起代码。有问题或者有使用心得,欢迎发帖讨论或者 QQ 群里讨论 497460177

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 34 条回复 时间 点赞
思寒_seveniruby 将本帖设为了精华贴 08月31日 09:59

unittest 还没学会,又要放弃了吗?

逗爸比 回复

这两个理念都差不多

这个处理弹框的看起来很好用啊

能把你们的框架介绍下么

vegetableBird 回复

这个文章不是已经介绍了吗?还要介绍什么

匿名 #8 · 2017年09月08日

查看 bundleId 的命令应该是:ideviceinstaller -l 哈~

已修改

是不是就是说,用这个就可以代替 appium 来完成 ios 的自动化测试了?没怎么接触 ios,所以弱弱的问问

jierong01 回复

是的

codeskyblue 回复

在 windows 上可以用吗?如果可以,那我要开干了

jierong01 回复

你需要一个苹果电脑运行 wda

codeskyblue 回复

额~忧伤,先 mark,以后再开干~感谢~

mark,感谢分享

刚才对着这个 对其他 app 试写了一次,好多感概。游戏资源有引擎那层太坑了,要不 UI 自动化和互联网 0 差别。。

陈子昂 回复

原生应用的测试是不是很好写

mark,感谢分享

楼主,最近我正在尝试用 facebooko-wda 写 iOS 自动化测试脚本。目前遇到一个问题,如何获取同类元素的个数?
lis=s(className='XCUIElementTypeCell')
i=len(lis)
模仿 appium 的语法写的,运行时错误提示: i=len(lis)
TypeError: object of type 'Selector' has no len()
请问楼主 wda 有什么类似的函数可以用吗?谢谢!

马家爵 回复

selector 类里不是有 count 么

def count(self):
return len(self.find_element())

vegetableBird 回复

真乃高人也!解决了我的问题。谢谢!

马家爵 回复

好好读读代码,不着急写

codeskyblue ATX 文档 - iOS 控件操作 API 中提及了此贴 12月28日 09:47

https://github.com/openatx/facebook-wda/tree/master/examples/com.netease.cloudmusic
楼主,这个 git 地址失效了呢,有新的地址吗?可以分享下吗

http://localhost:8100/inspector
楼主你有遇到启动 inspector 服务获取控件非常慢的情况吗

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44

@codeskyblue
博主,写测试脚本工作量还是不少,有办法录制测试脚本么?

Chengfei Xiao 回复

目前这还只是维持在一个基础库的状态。暂时我也不清楚什么录制工具

simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08

请问下,WebDriverAgent 能不能一台电脑同时连接多台真机呢?

michenging 回复

可以的呀

楼主大神,请问苹果上通过 wda 借助 xctest 的应用测试,是不是在测试时苹果手机都必须连着苹果电脑???有可以无线进行测试的思路吗?

set_alert_callback 无法使用了 有替代方案吗

魂魄君 回复

有一个 watch_and_click 你看看官方文档

大佬,我看 atx 的的 ios 和 android 分别用两个库维护,写法还不一样,那 app 自动化脚本要写两套嘛?

Sean Pan 回复

是的,不同的系统不同的库。其实我比较理解你同一套脚本解决不同平台的问题,这个直接在上层再封装一个库就可以了

codeskyblue 回复

能想到的也是这个方法,然后设置一个平台关键字,通过关键字来判断是调用 uiautomator2 还是 facebook-wda 的 api , 对了,atx 啥时候可以支持 flutter 开发的 app 啊,今天试了下可以点击,但是无法输入文本

38楼 已删除
仅楼主可见
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册