对于自动化测试来讲,核心技能就是对象的定位了。无论是web页面上的按钮或输入框,仍是移动app上的一个按钮或输入框,咱们要想对其进行点击或输入操做,前提是要先找到这个对象。css
webdriver提供了八种元素定位的方法:python
- id
- name
- class name
- tag name
- link text
- partial link text
- xpath
- css selector
在python语言中对应的定位方法以下:android
find_element_by_id()ios
find_element_by_name()web
find_element_by_class_name()app
find_element_by_tag_name()学习
find_element_by_link_text()测试
find_element_by_partial_link_text()ui
find_element_by_xpath()spa
find_element_by_css_selector()
一组元素定位的方法以下:
find_elements_by_id()
find_elements_by_name()
find_elements_by_class_name()
find_elements_by_tag_name()
find_elements_by_link_text()
find_elements_by_partial_link_text()
find_elements_by_xpath()
find_elements_by_css_selector()
Appium彻底继承了WebDriver中所定义的这些方法,除此以外对其进行了扩展,以便适合移动端对象的定位与操做。
由Mobile JSON Wire Protocol协议中定义的方法,更适合移动设备上的控件定位。
对于python来讲,在WebDriver的方法的基础上增长了下列方法:
find_element_by_accessibility_id()
find_elements_by_accessibility_id()
find_element_by_android_uiautomator()
find_elements_by_android_uiautomator()
可是咱们对照查询到的元素,能够发现不少的定位方法没法实现。
点击审查元素,发现根本就没有name什么的,最多的仍是class、id元素。
因此咱们只须要学习id、class、xpath定位就能够完成定位元素的目的了。
通过我几回测试,发现app的id值有两个属性能够表示,分别是id和resource-id。
若是id只有一个,那么就使用find_element_by_id来查询。
# coding:utf-8 import time from appium import webdriver # 初始化 desired_caps = {} # 使用哪一种移动平台 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查询,当有多台设备时,须要声明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.android.settings' # com.tencent.mobileqq #界面名 desired_caps['appActivity'] = '.Settings' # 启动服务 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) driver.find_element_by_id('com.android.settings:id/search').click() time.sleep(5) driver.quit()
启动这个程序,咱们能够看到点击了搜索按钮,进入了搜索界面。
而id值不是每一个元素都会显示的,而resource-id能够查询到,可是在大多数时候resource-id是一系列元素的id,因此咱们须要使用find_elements_by_id方法来查询id。
# coding:utf-8 import time from appium import webdriver # 初始化 desired_caps = {} # 使用哪一种移动平台 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查询,当有多台设备时,须要声明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.android.settings' # com.tencent.mobileqq #界面名 desired_caps['appActivity'] = '.Settings' # 启动服务 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) titles = driver.find_elements_by_id("com.android.settings:id/title") for title in titles: print(title.text) time.sleep(5) driver.quit()
class通常都不止一个,因此应该须要遍历一遍获得的元素,而后缩小搜索条件来得到目标元素。
咱们能够借助python中的pop()方法肯定想要这一组元素中的第几个,并对它进行点击或输入操做。
pop(0) 或pop(-1):默认得到一组元素中的最后一个。
pop(n):得到一组元素中的第n-1个。
一个class元素,使用find_element_by_class_name来查询。
# coding:utf-8 import time from appium import webdriver # 初始化 desired_caps = {} # 使用哪一种移动平台 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查询,当有多台设备时,须要声明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.android.settings' # com.tencent.mobileqq #界面名 desired_caps['appActivity'] = '.Settings' # 启动服务 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) driver.find_element_by_id('com.android.settings:id/search').click() driver.find_element_by_class_name("android.widget.EditText").send_keys("hello") time.sleep(5) driver.quit()
能够看到点击搜索按钮后出现后,在输入框输入了hello。
若是class元素有不少,就可使用find_elements_by_class_name来查询。
# coding:utf-8 import time from appium import webdriver # 初始化 desired_caps = {} # 使用哪一种移动平台 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查询,当有多台设备时,须要声明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.android.settings' #界面名 desired_caps['appActivity'] = '.Settings' # 启动服务 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) text_views = driver.find_elements_by_class_name("android.widget.TextView") for text_view in text_views: print(text_view.text) time.sleep(5) driver.quit()
在webdriver上xpath定位是功能强大的一种定位方式。我我的惯用于此方法来定位web页面上的元素。可是在android上要定位的是控件,而非页面元素,xpath定位的写法也会有所不一样。
# coding:utf-8 import time from appium import webdriver # 初始化 desired_caps = {} # 使用哪一种移动平台 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查询,当有多台设备时,须要声明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.android.settings' # com.tencent.mobileqq #界面名 desired_caps['appActivity'] = '.Settings' # 启动服务 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) driver.implicitly_wait(5)#隐式等待,下一章会讲解 driver.find_element_by_id("com.android.settings:id/search").click() driver.find_element_by_class_name("android.widget.EditText").send_keys("hello") driver.find_element_by_xpath("//*[@content-desc='收起']").click() time.sleep(5) driver.quit()
就目前而言吧,我以为appium的xpath定位很很差使用,多是由于还不够熟练的缘由吧。
# coding:utf-8 import time from appium import webdriver # 初始化 desired_caps = {} # 使用哪一种移动平台 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查询,当有多台设备时,须要声明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.android.settings' # com.tencent.mobileqq #界面名 desired_caps['appActivity'] = '.Settings' # 启动服务 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) elements = driver.find_elements_by_xpath("//*[contains(@text,'设')]") for element in elements: print(element.text) time.sleep(5) driver.quit()
和webdriver同样,若是使用find_element_by_xx方法,若是传入一个没有的特征,会报NoSuchElementException的错误。若是使用find_elements_by_xx方法,若是传入一个没有的特征,不会报错,会返回一个空列表。