Appium(六):元素定位

1. 元素定位

对于自动化测试来说核心技能就是对象的定位了。不管是web页面上按钮或输入框,还是移动app上的一个按钮或输入框,我们要想对其进行点击或输入操作,前提是要先找到这个对象。

webdriver提供了八种元素定位的方法:

  • id
  • name
  • class name
  • tag name
  • link text
  • partial link text
  • xpath
  • css selector

python语言中对应的定位方法如下:

find_element_by_id()

find_element_by_name()

find_element_by_class_name()

find_element_by_tag_name()

find_element_by_link_text()

find_element_by_partial_link_text()

find_element_by_xpath()

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协议中定义的方法,更适合移动设备上的控件定位。

  • ios uiautomation:一个递归的、对应使用UIAutomation library搜索元素的字符串(IOS-only)
  • android uiautomator:一个递归的、对应使用UIAutomation Api搜索元素的字符串(Android-only)
  • accessibility id:一个递归的、对应本地Accessibility选项实现的Id/Name进行元素搜索的字符串

 对于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定位就可以完成定位元素的目的了。 

1.1 id定位

经过我几次测试,发现app的id值有两个属性可以表示,分别是idresource-id

如果id只有一个,那么就使用find_element_by_id来查询。

  1. # coding:utf-8
  2. from time import sleep
  3. from appium import webdriver
  4.  
  5. # 初始化
  6. desired_caps = {}
  7. # 使用哪种移动平台
  8. desired_caps['platformName'] = 'Android'
  9. # Android版本
  10. desired_caps['platformVersion'] = '5.1.1'
  11. #使用adb devices -l 查询,当有多台设备时,需要声明
  12. desired_caps['deviceName'] = '127.0.0.1:62001'
  13. #包名
  14. desired_caps['appPackage'] = 'com.android.settings'
  15. # com.tencent.mobileqq
  16. #界面名
  17. desired_caps['appActivity'] = '.Settings'
  18.  
  19. # 启动服务
  20. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
  21.  
  22. driver.find_element_by_id('com.android.settings:id/search').click()
  23.  
  24. time.sleep(5)
  25.  
  26. driver.quit()

启动这个程序,我们可以看到点击了搜索按钮,进入了搜索界面。

id值不是每个元素都会显示的,而resource-id可以查询到,但是在大多数时候resource-id是一系列元素的id,所以我们需要使用find_elements_by_id方法来查询id。

  1. # coding:utf-8
  2. from time import sleep
  3. from appium import webdriver
  4.  
  5. # 初始化
  6. desired_caps = {}
  7. # 使用哪种移动平台
  8. desired_caps['platformName'] = 'Android'
  9. # Android版本
  10. desired_caps['platformVersion'] = '5.1.1'
  11. #使用adb devices -l 查询,当有多台设备时,需要声明
  12. desired_caps['deviceName'] = '127.0.0.1:62001'
  13. #包名
  14. desired_caps['appPackage'] = 'com.android.settings'
  15. # com.tencent.mobileqq
  16. #界面名
  17. desired_caps['appActivity'] = '.Settings'
  18. # 启动服务
  19. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
  20.  
  21. titles = driver.find_elements_by_id("com.android.settings:id/title")
  22. for title in titles:
  23. print(title.text)
  24.  
  25. time.sleep(5)
  26.  
  27. driver.quit()

1.2 class定位

class一般都不止一个,所以应该需要遍历一遍得到的元素,然后缩小搜索条件来获得目标元素。

我们可以借助python中的pop()方法确定想要这一组元素中的第几个,并对它进行点击或输入操作。

pop(0) 或pop(-1):默认获得一组元素中的最后一个。

pop(n):获得一组元素中的第n-1个。

一个class元素,使用find_element_by_class_name来查询。

  1. # coding:utf-8
  2. import time
  3. from appium import webdriver
  4.  
  5. # 初始化
  6. desired_caps = {}
  7. # 使用哪种移动平台
  8. desired_caps['platformName'] = 'Android'
  9. # Android版本
  10. desired_caps['platformVersion'] = '5.1.1'
  11. #使用adb devices -l 查询,当有多台设备时,需要声明
  12. desired_caps['deviceName'] = '127.0.0.1:62001'
  13. #包名
  14. desired_caps['appPackage'] = 'com.android.settings'
  15. # com.tencent.mobileqq
  16. #界面名
  17. desired_caps['appActivity'] = '.Settings'
  18.  
  19. # 启动服务
  20. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
  21.  
  22. driver.find_element_by_id('com.android.settings:id/search').click()
  23. driver.find_element_by_class_name("android.widget.EditText").send_keys("hello")
  24.  
  25. time.sleep(5)
  26.  
  27. driver.quit()

可以看到点击搜索按钮后出现后,在输入框输入了hello。

 

 

如果class元素有很多,就可以使用find_elements_by_class_name来查询。

  1. # coding:utf-8
  2. import time
  3. from appium import webdriver
  4.  
  5. # 初始化
  6. desired_caps = {}
  7. # 使用哪种移动平台
  8. desired_caps['platformName'] = 'Android'
  9. # Android版本
  10. desired_caps['platformVersion'] = '5.1.1'
  11. #使用adb devices -l 查询,当有多台设备时,需要声明
  12. desired_caps['deviceName'] = '127.0.0.1:62001'
  13. #包名
  14. desired_caps['appPackage'] = 'com.android.settings'
  15. #界面名
  16. desired_caps['appActivity'] = '.Settings'
  17.  
  18. # 启动服务
  19. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
  20.  
  21. text_views = driver.find_elements_by_class_name("android.widget.TextView")
  22. for text_view in text_views:
  23. print(text_view.text)
  24.  
  25. time.sleep(5)
  26.  
  27. driver.quit()

1.3 xpath 

webdriver上xpath定位是功能强大的一种定位方式。我个人惯用于此方法来定位web页面上的元素。但是在android上要定位的是控件,而非页面元素xpath定位的写法也会有所不同。 

  1. # coding:utf-8
  2. import time
  3. from appium import webdriver
  4.  
  5. # 初始化
  6. desired_caps = {}
  7. # 使用哪种移动平台
  8. desired_caps['platformName'] = 'Android'
  9. # Android版本
  10. desired_caps['platformVersion'] = '5.1.1'
  11. #使用adb devices -l 查询,当有多台设备时,需要声明
  12. desired_caps['deviceName'] = '127.0.0.1:62001'
  13. #包名
  14. desired_caps['appPackage'] = 'com.android.settings'
  15. # com.tencent.mobileqq
  16. #界面名
  17. desired_caps['appActivity'] = '.Settings'
  18.  
  19. # 启动服务
  20. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
  21. driver.implicitly_wait(5)#隐式等待,下一章会讲解
  22. driver.find_element_by_id("com.android.settings:id/search").click()
  23. driver.find_element_by_class_name("android.widget.EditText").send_keys("hello")
  24. driver.find_element_by_xpath("//*[@content-desc='收起']").click()
  25.  
  26. time.sleep(5)
  27.  
  28. driver.quit()

就目前而言吧,我觉得appium的xpath定位很不好使用,可能是因为还不够熟练的原因吧。

  1. # coding:utf-8
  2. import time
  3. from appium import webdriver
  4.  
  5. # 初始化
  6. desired_caps = {}
  7. # 使用哪种移动平台
  8. desired_caps['platformName'] = 'Android'
  9. # Android版本
  10. desired_caps['platformVersion'] = '5.1.1'
  11. #使用adb devices -l 查询,当有多台设备时,需要声明
  12. desired_caps['deviceName'] = '127.0.0.1:62001'
  13. #包名
  14. desired_caps['appPackage'] = 'com.android.settings'
  15. # com.tencent.mobileqq
  16. #界面名
  17. desired_caps['appActivity'] = '.Settings'
  18.  
  19. # 启动服务
  20. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
  21.  
  22. elements = driver.find_elements_by_xpath("//*[contains(@text,'设')]")
  23. for element in elements:
  24. print(element.text)
  25.  
  26. time.sleep(5)
  27.  
  28. driver.quit()

和webdriver一样,如果使用find_element_by_xx方法,如果传入一个没有的特征,会报NoSuchElementException的错误。如果使用find_elements_by_xx方法,如果传入一个没有的特征,不会报错,会返回一个空列表。

原文作者:@小灰灰
本文为作者原创,转载请注明出处:https://www.cnblogs.com/liuhui0308/archive/2004/01/13/12015458.html

原文地址:https://www.cnblogs.com/nini0806/p/13685905.html