Appium-desktop 下载地址:https://github.com/appium/appium-desktop/releases
一般功能
这些能力跨越多个驱动因素。
仅限****Android
这些功能仅适用于基于Android的驱动程序(例如 UiAutomator2)。
仅限****iOS
这些功能仅适用于XCUITest驱动程序和过时的UIAutomation驱动程序。
appium调用应用
1、调用已安装的包
from appium import webdriver
from time import sleep
desired_caps = {
'platformName': 'Android',
'deviceName': 'B7E0117228000104',
'platformVersion': '7.0',
'adbPort' : '5148',
'appPackage':'com.android.calculator2',
'appActivity':'com.android.calculator2.Calculator'
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
driver.find_element_by_id("com.android.calculator2:id/digit_1").click()
driver.find_element_by_id("com.android.calculator2:id/digit_5").click()
driver.find_element_by_id("com.android.calculator2:id/digit_9").click()
driver.find_element_by_id("com.android.calculator2:id/del").click()
driver.find_element_by_id("com.android.calculator2:id/digit_9").click()
driver.find_element_by_id("com.android.calculator2:id/digit_8").click()
driver.find_element_by_id("com.android.calculator2:id/op_add").click()
driver.find_element_by_id("com.android.calculator2:id/digit_6").click()
driver.find_element_by_id("com.android.calculator2:id/op_div").click()
driver.find_element_by_id("com.android.calculator2:id/digit_8").click()
driver.find_element_by_id("com.android.calculator2:id/eq").click()
sleep(3)
driver.quit()
2、安装并调用未安装的包
{
"platformName": "Android",
"platformVersion": "7.0",
"deviceName": "FFK0116B30000505",
"app": "D:\weixin.apk",
"noReset": true,
"adbPort": "5148"
}
Appium的基本使用
appium下包含2个包,common和webdriver,common下仅有一个exceptions,appium.common.exceptions所有appium中可能发生的异常。
其他操作及功能都在webdriver下:common、mobilecommand、webdriver、webelement。
1、app对象
Appium使用adb来与目标机器通讯,因此对于真机和模拟器操作几乎都是相同的,如何建立模拟器在此不再赘述。在Appium GUI点击 Launch 就可以启动 Appium Server。Appium Server 默认会监听 http://localhost:4723用于RPC通讯。dr为当前正在活动的 activity 对象,可以使用findElementByXXX 的方法来获取 Activity中的元素。所有Element后带s的函数,均获得所有匹配的元素,不带s的函数获得第一个匹配的元素。
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
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) #启动Remote RPC
WebDriver****对象的方法和属性:
driver.page_source #获取当前页面的源
driver.get_screenshot_as_file('/Screenshots/foo.png') #获取截图存入指定的路径
driver.get_window_size(windowHandle='current') #获取手机屏幕分辨率
driver.set_window_size(width,height) #设置屏幕分辨率
driver.orientation #获取方向
driver.orientation = 'landscape' #设置方向
driver.def desired_capabilities() #返回 设定的运行参数
driver.get_window_position()# 获取当前坐标位置
driver.find_element_by_定位方式(value) #查找元素
driver.find_element(by. 定位方式,"ag2") #查找元素,需from selenium.webdriver.common.by import By
输入操作
driver.scroll(el1,el2) #点击/触摸操作,从元素origin_el滚动至元素destination_el
driver.drag_and_drop(el1,el2) #将元素origin_el拖到目标元素destination_el
driver.tap([(x,y),(x1,y1)],500) # driver.tap([(100, 20), (100, 60), (100, 100)], 500) 模拟手指点击(最多五个手指),可设置按住时间长度(毫秒)
driver.tap(int fingers, WebElement element, int duration) #点击element控件中心点按下,duration*5毫秒秒后松开,如此重复fingers次。
driver.tap(int fingers, int x, int y, int duration) #点击(x,y)点按下,duration*5毫秒后松开,如此重复fingers次。
driver.pinch(element=None, percent=200, steps=50) #在元素上执行模拟双指捏(缩小操作)
driver.zoom(element=None, percent=200, steps=50): #在元素上执行放大操作,双指放大,和pinch相反的操作。
driver.swipe(x1,y1,x2,y2, duration =500) #从(start_x,start_y)滑到(end_x,end_y),分duration步滑,每一步用时是5毫秒。
driver.flick(x1,y1,x2,y2) #按住A点后快速滑动至B点
driver.shake()#摇一摇手机
drvier.lock(seconds):#锁屏一段时间,iOS专有
driver.keyevent(keycode, metastate=None): #发送按键码(安卓仅有),按键码可以上网址中找到
driver.press_keycode(self, keycode, metastate=None):#发送按键码(安卓仅有),按键码可以上网址中找到
driver.long_press_keycode(self, keycode, metastate=None): #发送一个长按的按键码(长按某键)
输入法
driver.hide_keyboard(key_name=None, key=None, strategy=None):#隐藏键盘,iOS使用key_name隐藏,安卓不使用参数
driver.available_ime_engines(): #返回安卓设备可用的输入法
driver.is_ime_active(): #安卓用法,检查设备是否有输入法服务活动,返回真/假。
driver.activate_ime_engine(engine):#激活安卓设备中的指定输入法,设备可用输入法可以从“available_ime_engines”获取
driver.deactivate_ime_engine(): #关闭安卓设备当前的输入法
driver.active_ime_engine(): #返回当前输入法的包名
app控制
driver.reset() #重置应用(相当于卸载重装应用)
driver.background_app(seconds) #把当前应用放到后台运行seconds秒
driver.open_notifications() #打开通知栏,只有Android可用(仅支持API 18 以上的安卓系统)
driver.is_app_installed(“com.xxxx”) #检查app是否有安装,返回 True or False
driver.install_app(app_path) #安装app,app_path为安装包路径
driver.remove_app(“com.xxx.”) #删除app
driver.launch_app() #启动app
driver.close_app() #关闭app,其实就是按home键把应用置于后台
driver.reset_app() #先closeApp然后在launchAPP
driver.close() #关闭当前窗口
driver.quit() #退出脚本运行并关闭每个相关的窗口连接
contexts/activity
driver.contexts #返回会话中的所有上下文,使用后可以识别H5页面的控件
driver. current_context#返回当前会话上下文
driver.Context #返回当前会话的当前上下文。
driver.current_activity()#获取当前的activity
driver.switch_to.context(None) #将上下文切换到默认上
driver.wait_activity(activity, timeout, interval=1): #等待指定的activity出现直到超时,interval为扫描间隔1秒, 即每隔几秒获取一次当前的activity。返回的True 或 False
driver.start_activity(app_package, app_activity, **opts): #在测试过程中打开任意活动。如果活动属于另一个应用程序,该程序的启动和活动被打开。这是一个安卓的方法
获取信息类API
driver.get_app_string() #获取默认系统语言对应的Strings.xml文件内的数据。
driver.get_app_string(String language) #查找某一个语言环境对应的字符串文件Strings.xml内数据。
driver.current_activity() #获取当前activity,比如(.ApiDemos)
driver.app_strings #应用的字符串
network
driver.network_connection#返回网络类型数值
driver.get_network_connection() 得到当前网络的状态
driver.set_network_connection(ConnectionType.WIFI_ONLY) #设置网络的状态。先加载from appium.webdriver.connectiontype import ConnectionType
位置服务
driver.toggle_location_services()#打开安卓设备上的位置定位设置
driver.set_location(latitude, longitude, altitude): #设置设备的纬度,经度,高度
- latitude纬度 - String or numeric value between -90.0 and 90.00
- longitude经度 - String or numeric value between -180.0 and 180.0
- altitude海拔高度- String or numeric value
文件pull/push
driver.pull_file('Library/AddressBook/AddressBook.sqlitedb') #从设备的指定路径获取文件(将设备上的文件pull到本地硬盘上)
driver.pull_folder(path) #将设备上的文件夹pull到本地硬盘上,一般远程文件为/data/local/tmp下的文件。
driver.push_file(path, data.encode('base64')) #将字符数组用64位格式写到远程目录的某个文件中。即把本地文件push到设备上。data = "some data for the file" path = "/data/local/tmp/file.txt"
2****、元素定位
1可定位元素:
Appium 定位方式是依赖于 Selenium 的。所以 Selenium 的定位方式Appium 都支持,除此之外还有Android 和 iOS 原生的定位方式,所以共有十多种定位方式。目前Appium 官方的定位方式中已经废除了name定位方式,另外tagName、linkText 、partialLinkText一般是在 web 页面使用,移动端很少用:
name # 元素的name属性,目前官方在移动端去掉这个定位方式,使用AccessibilityId替代
tagName # 元素的标签名
partialLinkText # 链接元素的部分显示文字
linkText # 链接元素的全部显示文字
cssSelector # Selenium 最强大的定位方法,比xpath速度快,但比xpath难上手
className # 元素的 class 属性
id # 元素的 id 属性
xpath # 比 css 定位方式稍弱一些的定位方法,但胜在容易上手,比较好使用,缺点就是速度慢一些。
AccessibilityId # Appium 中用于替代 name 定位方式
AndroidUIAutomator # Android 测试,最强大速度最快的定位方式
iOSNsPredicateString # iOS 谓词的定位方式,仅支持 XCTest 框架,需大于 iOS 9.3或以上
IosUIAutomation # iOS 谓词的定位方式,仅支持 UIAutomation 框架,需大于iOS 9.3或以下
iOSClassChain # 类似xpath的定位方式,仅支持XCTest框架,不如xpath和iOSNsPredicateString好
2定位方法:
常用的8种定位方法(与selenium通用)
driver.find_element_by_name() # name定位
driver.find_element_by_tag_name() # tag定位
driver.find_element_by_partial_link_text() # partial_link定位
driver.find_element_by_link_text() # link定位
driver.find_element_by_css_selector() # css 定位
driver.find_element_by_class_name() # class_name定位
driver.find_element_by_id() # id定位
driver.find_element_by_xpath() # xpath定位
移动端3种新增方法
driver.find_element_by_accessibility_id() # accessibility_id 定位
driver.find_element_by_android_uiautomator() # Android
driver.find_element_by_ios_uiautomation() # ios
通过****id****定位
仅支持 Android 4.2或以上,推荐使用,使用 id 能准确定位就使用id,id定位信息简洁不容易错误。
resrouce-id属性使用id定位:
driver.find_element_by_id('username')
driver.find_element_by_id("com.wuba.zhuanzhuan:id/azo")
也可以直接用id后面的内容driver.find_element_by_id("azo")
通过****class_name****定位
class属性使用class_name定位:(一般一个页面上的class属性不唯一,元素不唯一的话定位会报错了)Android 和 iOS,推荐使用。
self.driver.find_element_by_class_name('android.view.View').click()
driver.find_element_by_class_name("android.widget.RelativeLayout")
通过****xpath****定位
支持Android 和 iOS。但由于iOS 10开始使用的 XCUITest 框架所以不支持;定位速度很慢,所以官方现在不推荐大家使用。
driver.find_element_by_xpath("//android.widget.LinearLayout[1]/android.widget.XXX") #使用绝对路径定位
driver.find_element_by_xpath("//className") #使用相对路径定位
driver.find_element_by_xpath("//className[index]") #通过元素的索引定位
driver.find_element_by_xpath("//className[@label='更多信息']") #通过元素的属性定位,使用一种属性定位
driver.find_element_by_xpath("//className[@label='更多信息'][@isVisible='1']") #通过元素的属性定位,使用两种属性定位
driver.find_element_by_xpath("//className[contains(@label,'更多')]") #通过元素的属性定位,使用部分属性定位(最强大)
Xpath定位
self.driver.find_element_by_xpath("//android.widget.TextView[@text=' ']").click()
AccessibilityId
替代以前的name定位方式,推荐使用。在 Android 上主要使用元素的content-desc属性进行定位。在 iOS 上,主要使用元素的label或name(两个属性的值都一样)属性进行定位,
content-desc属性使用accessibility_id定位
driver.find_element_by_accessibility_id(u"我的").click()
driver.find_element_by_accessibility_id()
android_uiautomator ****定位
仅支持 Android 4.2或以上,可支持元素的单个属性和多个属性定位,推荐使用。元素的所有属性都可用android_uiautomator做定位,功能非常强大,且速度很快。
支持元素以下属性定位:index(int index)、text(String text)、resourceId(String id)、className(String className)、packageName(String packageName)、description(String desc)、checked(boolean val)、clickable(boolean val)、enabled(boolean val)、longClickable(boolean val)、password(boolean val)、selected(boolean val)、instance(int val)
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("username")').clear()
driver.find_element_by_android_uiautomator("new UiSelector().text("发送")") # 使用一种属性定位
driver.find_element_by_android_uiautomator ("new UiSelector().text("发送").clickable(true)") # 使用两种属性定位
通过text属性通过android_uiautomator定位的结果是个list,不能直接click。所以如果要点击需要取数组的值,比如下面是点击找到的第一个元素
driver.find_elements_by_android_uiautomator("new UiSelector().text("+关注")")[0].click()
通过****css_selector****定位(****webview****)
只适用于webview的html页面,继承自webdriver,与pc版本的UI测试一致
driver.find_element_by_css_selector()
通过****link_text****定位(****webview****)
只适用于webview容器中的html页面,继承自webdriver,与pc版本的UI测试一致
driver.find_element_by_link_text()
通过****name****定位
只适用于web view容器中的html页面
driver.find_element_by_name()
text属性可以使用name定位
driver.find_element_by_name(u'请输入用户名')
通过元素定位元素
可以先找到某个元素,然后再进一步定位元素
find_element_by_class_xpath(“xxx”).find_element_by_name(“yyy")
3、元素的方法
from appium.webdriver import webelement
element.tag_name() #返回元素的tagName属性,经实践返回的是class name
element.text #返回元素的文本值,注意:没有括号
element.click() #点击元素
element.submit() #提交表单
element.clear() #清除输入的内容
element.get_attribute(name) #获取 content-desc,但还不能保证返回的一定是 content-desc可获取的字符串类型:name(返回 content-desc 或 text)、text(返回 text)、className(返回 class,只有 API=>18 才能支持)、resourceId(返回 resource-id,只有 API=>18 才能支持)
可获取的布尔类型(如果无特殊说明, get_attribute 里面使用的属性名称和 uiautomatorviewer 里面的一致):enabled、checkable、checked、clickable、focusable、 focused、longClickable(返回 long-clickable)、scrollable、selected
element.is_slected() #返回元素是否选择。可以用来检查一个复选框或单选按钮被选中。
element.is_enabled() #返回元素是否可用True of False
element.send_keys(*value) #在元素中模拟输入(开启appium自带的输入法并配置了appium输入法后,可以输入中英文)
element.size() #获取元素的大小(高和宽)
element.location() #获取元素左上角的坐标
element.location.get('x') #返回element的x坐标, int类型
element.location.get('y') #返回element的y坐标, int类型
element.rect() #元素的大小和位置的字典