【备档】客户端自动化(主Android Appium + python
之前做分享写的文档,备档~
0.移动客户端自动化简介
客户端自动化测试的本质
定位对象 · 操作对象 · 校验对象
对象的定位应该是自动化测试的核心,要想操作、校验一个对象,首先应该识别这个对象。
一个对象具有特定的属性,譬如:文字、类型、位置等等。我们可以通过这些属性找到这对象。
移动客户端自动化测试常见框架
Android
- Monkey
- Monkeyrunner
- UIautomator
- Robotium
iOS
- UIAutomation
通用
- Appium
- Calabash
...
框架选择
- 支持平台,系统版本
- 是否需要源码
- 脚本语言
- 是否支持webview
...
浅谈移动端自动化测试框架和工具
http://blog.csdn.net/meyoung01/article/details/40076511
iOS自动化测试框架对比
http://www.jianshu.com/p/047035416095
1.Appium 思想·原理·环境搭建
Appium 思想
架构原理
- 左边的WebDriver script是我们的selenium测试脚本
- 中间是起的Appium的服务,Appium在这边起了一个Server,Appium Server接收webdriver 标准请求,解析请求内容,调⽤用对应的框架响应操作。如:脚本发送一个点击按钮的请求给appium server
- Appium server会把请求转发给中间件Bootstrap.jar ,它是用java写的,安装在手机上.Bootstrap 接收appium 的命令,最终通过调⽤用UiAutomator的命令来实现
- 最后执⾏行的结果由Bootstrap返回给Appium server
Appium环境搭建python篇(mac系统)
安装时使用VPN可能比淘宝源成功率更高~
2.定位对象 · 操作对象 · 校验对象
定位对象-Android
工具
UiAutomatorview (4.1下版本不支持)
启动方法
➜ ~ uiautomatorviewer
定位方法
查找客户端页面元素方法
以下是Appium给出的所有方法(但不一定支持!)
|
查找页面中存在的单个元素
|
查找页面中存在多个元素(返回数组)
|
查找方法
|
|---|---|---|
|
find_element |
find_elements |
def find_element(self, by=By.ID, value=None) 被其他find_element方法调用 |
| find_element_by_accessibility_id | find_elements_by_accessibility_id |
Accessibility ID在Android上面就等同于contentDescription,这个属性是方便一些生理功能有缺陷的人使用应用程序的。 UiAutomatorview中content-desc |
| find_element_by_android_uiautomator | find_elements_by_android_uiautomator | 使用android_uiautomator表达 |
| find_element_by_class_name | find_elements_by_class_name | UiAutomatorview中class |
| find_element_by_id | find_elements_by_id | UiAutomatorview中resource-id |
| find_element_by_ios_uiautomation | find_elements_by_ios_uiautomation | - |
| find_element_by_link_text | find_elements_by_link_text | UiAutomatorview中text |
| find_element_by_name | find_elements_by_name | Appium 1.5 版本已经被废除 |
| find_element_by_partial_link_text | find_elements_by_partial_link_text |
UiAutomatorview中text,可以匹配部分文字 譬如:美食(XX家) |
| find_element_by_tag_name | find_elements_by_tag_name | Appium 1.0 版本已经被废除 |
| find_element_by_xpath | find_elements_by_xpath | xpath,强烈不推荐 |
find_element_by_android_uiautomator() 举栗子
def autotest_find_name_by_uiautomator(self, name):
return self.driver.find_element_by_android_uiautomator('new UiSelector().text("%s")' % name)
find_element_by_android_uiautomator()中的字符串为Uiautomator的写法,主要有以下几种方法:
new UiSelector().text("%s")
new UiSelector().textContains("%s")
new UiSelector().className("%s")
new UiSelector().resourceId("%s")
textContains类似于find_element_by_partial_link_text,可以做部分文字匹配
操作对象
以下是常用的方法,更多的方法可以通过源码或提示获得
tips:某些方法可能在特定系统不支持
# 点击对象
.click()
# 文本框输入文字
.send_keys("%s")
#获取控件文字
.text
# 从(startx,starty)滑到(endx,endy),分duration步滑,每一步用时是5毫秒。
driver.swipe(int startx, int starty, int endx, int endy, int duration)
# 按手机固定键,key值定义在AndroidKeyCode类中
# keycode http://blog.csdn.net/crisschan/article/details/50419963
driver.send_key_event(int key)
# 获取当前的activity
driver.current_activity()
# 等待指定的activity出现,interval为扫描间隔1秒
driver.wait_activity(activity, timeout, interval=1)
...
校验对象
在Python环境下,Appium 官方推荐使用unittest来维护测试用例,unittest提供了多种assert方法,我们可以通过这些方法来做校验。
unittest中常用的assert语句
http://www.cnblogs.com/paulwinflo/p/5742142.html
校验方式
- 校验控件是否展示
- 校验控件中的数据(文本)是否正确
- 图片对比
- ...
代码实现
校验元素非空
def assert_element_exist_by_x(self, how, what, msg=None):
"""
通过*方法验证元素非空
:param how:find_element_by_* methods
(By.CLASS_NAME/By.TAG_NAME/By.NAME/By.PARTIAL_LINK_TEXT/By.NAME/By.XPATH/By.ID)
:param what:
:param msg:
"""
try:
if how ==By.NAME:
self.assertIsNotNone(self.autotest_find_name_by_uiautomator(what), msg)
else:
self.assertIsNotNone(self.driver.find_element(by=how, value=what), msg)
return True
except Exception:
print "xxxxx"
3.用例编写
官方栗子
import os
import unittest
from appium import webdriver
from time import sleep
# Returns abs path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p)
)
class ContactsAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.2'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = PATH(
'../../../sample-code/apps/ContactManager/ContactManager.apk'
)
desired_caps['appPackage'] = 'com.example.android.contactmanager'
desired_caps['appActivity'] = '.ContactManager'
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def tearDown(self):
self.driver.quit()
def test_add_contacts(self):
el = self.driver.find_element_by_accessibility_id("Add Contact")
el.click()
textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
textfields[0].send_keys("Appium User")
textfields[2].send_keys("someone@appium.io")
self.assertEqual('Appium User', textfields[0].text)
self.assertEqual('someone@appium.io', textfields[2].text)
self.driver.find_element_by_accessibility_id("Save").click()
# for some reason "save" breaks things
alert = self.driver.switch_to_alert()
# no way to handle alerts in Android
self.driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)').click()
self.driver.press_keycode(3)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(ContactsAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
setup
在Appium中所有动作的前提是要启动一个session,启动方法就是
http://127.0.0.1:4723/wd/hub/session
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
其中desired_caps是配置信息,它告诉server 本次测试的具体内容,譬如:
- 本次测试是启动浏览器还是启动移动设备?
- 是启动andorid还是启动ios?
- 启动android时,app的package是什么?
- 启动android时,app的activity是什么?
必要的desired_caps参数
desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '4.2' desired_caps['deviceName'] = '022MWW146T007732' desired_caps['app'] = 'XXX.apk'
- platformName:使用哪种移动平台。iOS, Android, orFirefoxOS?
- deviceName:启动哪种设备,是真机还是模拟器?iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android Emulator, Galaxy S4, etc...
- app:应用的绝对路径,注意一定是绝对路径。如果指定了appPackage和appActivity的话,这个属性是可以不设置的。另外这个属性和browserName属性是冲突的。
- automationName:使用哪种自动化引擎。appium(默认)还是Selendroid?
- appActivity:待测试的app的Activity名字。比如MainActivity, .Settings。注意,原生app的话要在activity前加个"."。
- appPackage:待测试的app的java package。比如com.example.android.myApp, com.android.settings。
teardown
self.driver.quit()
4.其他
- Android 获取当前Activity、包名方法
adb shell dumpsys activity | grep "mFocusedActivity"
adb shell pm list package
- 元素定位不到/没有id的方法
麻烦开发增加特有、不重复的id



浙公网安备 33010602011771号