Appium 在 Android UI 测试中的应用

标签: startup | 发表时间:2016-09-06 00:00 | 作者:
出处:http://itindex.net/admin/pagedetail

Android 测试工具与 Appium 简介

Appium 是一个 C/S 架构的,支持 Android/iOS Native, Hybrid 和 Mobile Web Apps 的测试框架,与测试程序通过 Selenum Webdriver 协议通讯。Webdriver 的好处是通过 HTTP RPC 的方式调用 Server 上的过程,编写测试脚本不受语言的限制,无论是 Python, Java, NodeJS 均可以方便的编写测试。本文中将使用 Python 进行编程。

起因是因为市场部的同事抛来如下需求:批量添加一些微信好友。直接抓取请求进行重放的方法是不靠谱的,微信与服务端的通讯均加密,Pass。考虑使用 xposed 等框架 hook 相关函数进行操作。但是 xposed 需要越狱,且开发复杂,Pass。后来想到了使用 UI 测试工具进行模拟操作,开发较为简单。

Android UI 测试工具有很多种,如 Monkey, UIAutomator, Selendroid, Robotium 等。其中 UIAutomator, Monkey, Selendroid 均为非侵入式的 UI 测试,也就是不需要修改源代码,只要安装了目标程序就可以进行测试。Robotium 需要与源码一同编译测试。Appium 实际上就是一个测试工具的统一调度软件,将不同的非侵入式测试工具整合在一起,对外提供统一的 API。在 Android 2.3 以前的版本,Appium 会调用 Selendroid ,之后的版本会直接使用 UIAutomator,iOS 下使用 UIAutomation。Appium 还支持 FirefoxOS 的 UI 测试。

图片

安装 Appium

官网给出了命令行下的安装方法。但实际上 Appium 有 GUI 版本,更适合在 Windows/MacOS 下使用。Windows 下需要安装 .NET Framework。

   > brew install node      # get node.js
> npm install -g appium  # get appium
> npm install wd         # get appium client
> appium &               # start appium
> node your-appium-test.js

Appium 需要依赖 Android SDK 编译在手机端运行的两个插件,因此需要首先安装相应的 Android SDK 版本。这里直接使用了 Android Studio 中自带的 SDK Manager。在 SDK Manager 中选择和测试机相对应的 SDK Platform 和较新的 Build-tools,如果需要使用模拟器测试还要装对应的 ARM/x86 System Image,以及 Intel HAXM Installer,用于加速 x86 虚拟机。Appium 使用 adb 来与目标机器通讯,因此对于真机和模拟器操作几乎都是相同的,如何建立模拟器在此不再赘述。

安装完成后需要在 Appium GUI 中配置 Android SDK 目录,随后选择 Android,点击 Launch 就可以启动 Appium Server。
图片
图片

Appium Server 默认会监听 http://localhost:4723,用于 RPC 通讯。下面我们就可以打开熟悉的编程环境,编写 UI 测试用例了。这里使用 Python 进行编写,需要先安装 Appium 的 Python Client ,然后再 python 中使用 appium.webclient 就可以连接 Appium server了。

   pip install Appium-Python-Client

使用 Appium 进行 UI 控制

根据注释修改相应属性后即可运行测试。手机需要打开 ADB 调试,执行完以下代码后,Appium 会在手机上安装 Appium Settings 和 Unlock 两个程序,随后微信会被启动。

   from appium import webdriver
 
desired_caps = {}
desired_caps['platformName'] = 'Android'  #测试平台
desired_caps['platformVersion'] = '5.1'   #平台版本
desired_caps['deviceName'] = 'm3_note'    #设备名称,多设备时需区分
desired_caps['appPackage'] = 'com.tencent.mm'  #app package名
desired_caps['appActivity'] = '.ui.LauncherUI' #app默认Activity
dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) #启动Remote RPC

Selenum Webdriver 使用了一种类似于 JS 中的 DOM 模型的方法来选择页面中的元素。dr 为当前正在活动的 activity 对象,可以使用 findElementByXXX 的方法来获取 Activity 中的元素。所有 Element 后带 s 的函数,均获得所有匹配的元素,不带 s 的函数获得第一个匹配的元素。

查询函数

1. findElement(s)ByName

在 Android 中基本没用。Android UI 没有 Name 这个属性。有说可以使用 text 值获取。但我并没有成功

2. findElement(s)ByClassName

通过类名来获取元素,用法如下:

   item_list = dr.find_elements_by_class_name("android.widget.LinearLayout")
item_list[2].click()
3. findElementById

通过 resource_id 来获取元素,每个 Activity 中都是唯一的,用法如下

   t = dr.find_element_by_id("com.tencent.mm:id/f7")
t.send_keys(wechatId)
4. findElement(s)ByAccessbiltiyId

在 Android 上 AccessbilityID 实际就是 contentDescription 。这个属性是为了方便视力受损人士使用手机所设置。开启 TTS 后系统会朗读相关控件的 contentDescription。

5. findElement(s)ByXPath

通过 XML Path 描述来寻找元素。我没有成功的获取到,可能是 XPath 写的有问题。

   s = dr.find_element_by_xpath("//android.widget.TextView[contains(@text,'搜索')]")
s.click()
6. findElementByAndroidUIAutomator

通过 UIAutomator 的选择器来获取元素。因为 Appium 在 Android 上实际是调用的 UIAutomator,所以可以通过 UIAutomator 的选择器来选择元素。

   el = dr.find_element_by_android_ui_automator("new UiSelector().text(\"搜索\")")
el.click()

操作函数

操作函数用于操作选定的元素,有很多,以下仅列举几个,更多的请查阅手册。

  1. click
  2. send_keys
  3. clear

查询函数返回的元素对象可以像 JS 中的 dom 元素一样,继续使用查询函数来选定其子元素。用例如下。

   search = dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout")
search.click()

如何确定查询规则

了解了相关的函数后,下面就应对 UI 进行定位了。如果是自己团队开发的程序,推荐让开发同学在所有的空间上都添加 resource_id 进行绝对定位。如果碰到没有谈价 resource_id 的元素,那就要使用别的办法进行定位了。

1. UI Automator Viewer

UI Automator Viewer 是 Android 官方的 UI 定位工具,位于 sdk/tools 下。运行后会打开 viewer 界面。点击获取按钮即可获取当前正在运行的 Activity 的 UI 结构。
图片

2. AppiumDriver getPageSource

AppiumDriver(Client) 可以很方便的获得当前正在运行的 Activity 的 UI 描述,随后可根据返回的 XML 文档来寻找元素。

   print dr.page_source

图片

确定元素位置后,即可根据前述的 Find 方法来查找/选择元素

编写完整的测试代码

正确的获取元素之后便可以获取元素相关的信息,随后使用各语言常用的测试框架编写测试即可,如 Java 的 JUnit,Nodejs 的 Mocha 等。

这里我使用 Appium 主要是为了模拟用户点击添加微信好友,所以完整的程序并没有使用到测试框架。相关的 UI 元素获取/操作方法供大家参考。

   # coding:utf-8
from appium import webdriver
from time import sleep


def addFriend(dr, id, dryRun=False):
    succ = False
    wechatId = str(id)
    dr.find_element_by_accessibility_id(r"更多功能按钮").click()
    item_list = dr.find_elements_by_class_name("android.widget.LinearLayout")
    try:
        item_list[2].click()
    except:
        print "Error! in item list len"
        return succ
    el = dr.find_element_by_class_name("android.widget.ListView")
    item_list = el.find_elements_by_class_name("android.widget.LinearLayout")
    try:
        item_list[1].click()
    except:
        print "Error! in item list len"
        return succ
    t = dr.find_element_by_id("com.tencent.mm:id/f7")
    t.send_keys(wechatId)
    search = dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout")
    search.click()
    try:
        freq = dr.find_element_by_id('com.tencent.mm:id/aqq')
        assert freq.text == u"操作过于频繁,请稍后再试。"
        print "Frequency too high! Sleep 300s"
        sleep(60)
        return succ
    except:
        pass

    try:
        dr.find_element_by_id('com.tencent.mm:id/a8x').click()
        addBtn = dr.find_element_by_id('com.tencent.mm:id/eu')
        if not dryRun:
            addBtn.click()
            succ = True
        print "Success Send Requests:" + wechatId
    except:
        print "No Such User Or Already a Friend:" + wechatId

    while True:
        try:
            dr.find_element_by_id('com.tencent.mm:id/fb').click()
        except:
            try:
                dr.find_element_by_id('com.tencent.mm:id/f4').click()
            except:
                break
    return True

def resetActivity(dr, desired_caps):
    dr.start_activity(desired_caps['appPackage'], desired_caps['appActivity'])

desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = 'm3_note'
desired_caps['appPackage'] = 'com.tencent.mm'
desired_caps['appActivity'] = '.ui.LauncherUI'
print "Trying connect to phone..."
dr = {}
try:
    dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
except Exception, e:
    print "Cannot Connect to phone :", e
    exit()
print "Successfully connect to phone."
print "Reading friend list..."
friendList = []
fp = open("friends.txt")
line = fp.readline().strip()
while line:
    friendList.append(line)
    line = fp.readline().strip()
print "Finish reading friends. Total: " + str(len(friendList))
print "Wait for Wechat's splash screen...."
for i in range(0, 10):
    print 10 - i
    sleep(1)
succ_list = []
fail_list = []
for i in friendList:
    try:
        succ = addFriend(dr, i, dryRun=False)
        if succ:
            succ_list.append(i)
        else:
            fail_list.append(i)
    except:
        fail_list.append(i)
        resetActivity(dr, desired_caps)

print "Succeed List:"
print "\n".join(succ_list)
print "Failed List:"
print "\n".join(fail_list)

dr.close()

相关 [appium android ui] 推荐:

Appium 在 Android UI 测试中的应用

- - IT瘾-startup
Android 测试工具与 Appium 简介. Appium 是一个 C/S 架构的,支持 Android/iOS Native, Hybrid 和 Mobile Web Apps 的测试框架,与测试程序通过 Selenum Webdriver 协议通讯. Webdriver 的好处是通过 HTTP RPC 的方式调用 Server 上的过程,编写测试脚本不受语言的限制,无论是 Python, Java, NodeJS 均可以方便的编写测试.

基于 Appium 的 Android UI 自动化测试

- - 美团点评技术团队
自动化测试是研发人员进行质量保障的重要一环,良好的自动化测试机制能够让开发者及早发现编码中的逻辑缺陷,将风险前置. 日常研发中,由于快速迭代的原因,我们经常需要在各个业务线上进行主流程回归测试,目前这种测试大部分由人工进行,费时费力,重复劳动多. 如果能将UI自动化测试与主流程回归结合到一起,一方面保证了代码质量,另一方面大大节约人力成本,可谓一举两得.

Android的UI布局总览

- - 博客园_首页
                  android布局的目的是为了实现不同屏幕比例适配而设计的,有五种布局类:FrameLayout、LinearLayout、AbsoluteLayout、RelativeLayout和TableLayout. 五大布局类的继承关系如下(以FrameLayout为例):.

谈谈Android的一些UI设计

- plidezus - 盒子UI
谈到应用程序设计,对设计师来说,Android就像是房间里的大象. 很多设计师会更希望这是iOS,在那里所有任何人都只需要关心iPhone手机,iPad和App Store. 然后没有人可以忽略Android,它目前已占据智能手机中最大的市场份额,且已经被广泛用于从平板电脑到电子阅读器等各种产品. 总之,谷歌的Android平台正在迅速遍地开花,品牌厂商们很难不注意到.

MIUI是个不错的Android UI系统

- Keven - Engadget 中国版
显然,点心不是唯一的专为中国用户打造的Android UI,你还可以选择民间的另一个版本:MIUI,也是不错,中国原创Android ROM小组出品,基于Android 2.2 原生开发,对短信和电话做了速度提升,同时整个UI和动画的切换也做了提升,感觉很不错,有兴趣的可以去官方网站去看看,目前支持Nexus One/HTC Desire G7,更多版本应该会在后续到来.

Android UI 组件开源软件

- - 移动开发 - ITeye博客
其实也算不上合集,只是将我经常用到的部分整理一下,如果您有好东西,也可以留言补充,. 可以参照应用Libraries for developers,ios的参照Libraries for developers Pro. https://github.com/JakeWharton/ActionBarSherlock (推荐).

appium windows下环境搭建

- - CSDN博客移动开发推荐文章
appium 介绍:Appium 是一个开源、跨平台的自动化测试工具,用于测试原生和轻量移动应用,支持 iOS, Android 和 FirefoxOS 平台. Appium 驱动苹果的 UIAutomation 库和 Android 的 UiAutomator 框架,使用 Selenium 的 WebDriver JSON 协议.

Android 平台的 Google Reader 更新 UI 并支持 Honeycomb

- 丁丁 - Engadget 中国版
Android 上的 Google Reader 软件总算更新了. 这次更新提供了新的用户界面以及 Honeycomb 平板计算机的支持,RSS 的重度使用者们,现在已经可以在 Xoom、Galaxy Tab 10.1 或其他兼容的平板计算机上,使用美观的双栏式界面浏览 RSS 订阅的文章了. 而此项 1.0.1 的更新也不仅仅针对平板设备更新,它也针对小屏幕设备的用户界面也换了新的面貌.

Android 3.0(蜂巢)交互&UI设计规范

- evan - 信息和交互 - UCD大社区
Android OS自上市以来,由于缺乏统一规划,使得不同设备在 1.5、1.6、2.0、2.1、2.2、2.3几大版本徘徊,本人用的HTC Hero(俗称G3)也是从1.5~2.3一个个版本,10多个rom手动刷机试过来的,过程及其纠结 ~. 多系统版本带来的问题就是缺乏交互、UI的一致性,外加硬件厂商HTC、摩托罗拉、三星、夏普(创新工场点心OS)、小米(MIUI)等公司热衷于UI的个性化发挥,以及民间高手的DIY rom 等因素,影响着安卓饭儿的用户体验,使各阶层用户徒增学习使用成本,也让APP开发者在不同版本兼容性间疲于奔命.