元素定位操作 API
定位一个元素
1、driver.find_element_by_id(id_value)
2、driver.find_element_by_class_name(class_value)
3、driver.find_element_by_xpath(xpath_value)
示例
通过 id 的形式,定位 ”放大镜“ 按钮,并点击
通过 class 的形式,定位 ”输入框“,输入 ”hello“
通过 xpath 的形式,定位 ”返回“ 按钮,并点击
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()
定位一组元素
1、driver.find_elements_by_id(id_value)
2、driver.find_elements_by_class_name(class_value)
3、driver.find_elements_by_xpath(xpath_value)
titles = driver.find_elements_by_id("com.android.settings:id/title")
for title in titles:
print(title.text)
text_views = driver.find_element_by_class_name("android.widget.TextView")
for text_view in text_views:
print(text_view.text)
elements = driver.find_element_by_xpath("//*[contains(@text,'设')]")
for element in elements:
print(element.text)
注意
1. 如果使用 find_element_by_xx 方法,如果传入一个没有的特征,会报NoSuchElementException 的错误。
- 如果使用 find_elements_by_xx 方法,如果传入一个没有的特征,不会报错,会返回一个空列表
元素等待
隐式等待
应用场景
针对所有定位元素的超时时间设置为同一个值的时候
概念
等待元素加载指定的时长,超出时长抛出NoSuchElementException异常
步骤
在获取 driver 对象后,使用 driver 调用 implicitly_wait 方法即可
示例
在 5 秒钟内,在《设置》程序中的 ”收起“ 按钮,如果找到则点击。如果找不到则观察对应错误信息。
from selenium.webdriver.support.wait import WebDriverWait
# -----
# 启动应用参数
# -----
driver.implicitly_wait(5)
search_button = driver.find_element_by_xpath("//*[contains(@content-desc,'收起')]")
search_button.click()
显式等待
应用场景
针对所有定位元素的超时时间设置为不同的值的时候
概念
等待元素加载指定的时长,超出时长抛出TimeoutException异常
步骤
-
导包
-
创建 WebDriverWait 对象
-
调用 WebDriverWait 对象的 until 方法
示例
在 5 秒钟内,每 1 秒在《设置》程序中的 ”返回“ 按钮,如果找到则点击。如果找不到则观察对应 错误信息。
from selenium.webdriver.support.wait import WebDriverWait
# -----
# 启动应用参数
# -----
# 创建WebDriverWait对象
wait = WebDriverWait(driver, 5, poll_frequency=1)
# 获取元素并设置超时时间和频率
search_button = wait.until(lambda x: x.find_element_by_xpath("//* [contains(@content-desc,'收起')]"))
# 点击搜索按钮
search_button.click()
隐式等待和显式等待的选择
作用域:
显式等待为单个元素有效,隐式为全局元素
方法:
显式等待方法封装在 WebDriverWait 类中,而隐式等待则直接通过 driver 实例化对象调用
关于 sleep 的形式
sleep 是固定死一个时间,不是不行,是不推荐。
元素等待可以让元素出来的第一时间进行操作。sleep 可能造成不必要的浪费。
滑动和拖拽事件
swipe 滑动事件
概念
· 从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动。
方法名
# 从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动
# 参数:
# start_x: 起点X轴坐标
# start_y: 起点Y轴坐标
# end_x: 终点X轴坐标
# end_y: 终点Y轴坐标
# duration: 滑动这个操作一共持续的时间长度,单位:ms
driver.swipe(start_x, start_y, end_x, end_y, duration=None)
例1 模拟手指从(100, 2000),滑动到(100, 1000)的位置
driver.swipe(100, 2000, 100, 1000)
例2 模拟手指从(100, 2000),滑动到(100, 100)的位置,持续5秒
driver.swipe(100, 2000, 100, 100, 5000)
scroll 滑动事件
概念
从一个元素滑动到另一个元素,直到页面自动停止。
方法名
# 从一个元素滑动到另一个元素,直到页面自动停止
# 参数:
# origin_el: 滑动开始的元素
# destination_el: 滑动结束的元素
driver.scroll(origin_el, destination_el)
例
save_button = driver.find_element_by_xpath("//*[@text='存储']")
more_button = driver.find_element_by_xpath("//*[@text='更多']")
driver.scroll(save_button, more_button)
drag_and_drop 拖拽事件
概念
从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置。
方法名
# 从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置
# 参数:
# origin_el: 滑动开始的元素
# destination_el: 滑动结束的元素
driver.drag_and_drop(origin_el, destination_el)
例
save_button = driver.find_element_by_xpath("//*[@text='存储']")
more_button = driver.find_element_by_xpath("//*[@text='更多']")
driver.drag_and_drop(save_button, more_button)
滑动和拖拽事件的选择
滑动和拖拽无非就是考虑是否有 “惯性” ,以及传递的参数是 “元素” 还是 “坐标”。 可以分成以下四种情况
有 “惯性” ,传入 “元素”,用scroll
无 “惯性” ,传入 “元素”,用drag_and_drop
有 “惯性” ,传入 “坐标”,用swipe,并且设置较短的 duration 时间
无 “惯性” ,传入 “坐标”,用swipe,并且设置较长的 duration 时间
TouchAction
轻敲操作
应用场景
模拟手指对某个元素或坐标按下并快速抬起。比如,固定点击(100, 100)的位置。
方法名
# 模拟手指对元素或坐标的轻敲操作
# 参数:
# element:元素
# x:x坐标
# y:y坐标
TouchAction(driver).tap(element=None, x=None, y=None).perform()
示例
- 打开《设置》
- 轻敲 “WLAN”
el = driver.find_element_by_xpath("//[contains(@text,'WLAN')]")
TouchAction(driver).tap(el).perform()
按下和抬起操作
应用场景
模拟手指一直按下,模拟手指抬起。可以用来组合成轻敲或长按的操作
方法名
# 模拟手指对元素或坐标的按下操作
# 参数:
# el:元素
# x:x坐标
# y:y坐标
TouchAction(driver).press(el=None, x=None, y=None).perform()
# 模拟手指对元素或坐标的抬起操作
TouchAction(driver).release().perform()
示例
使用坐标的形式按下 WLAN (650, 650),2 秒后,按下(650, 650)的位置,并抬起
TouchAction(driver).press(x=650, y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650, y=650).release().perform()
等待操作
应用场景
模拟手指等待,比如按下后等待 5 秒之后再抬起。
方法名
# 模拟手指暂定操作
# 参数:
# ms:暂停的毫秒数
TouchAction(driver).wait(ms=0).perform()
示例
使用坐标的形式点击 WLAN (650, 650),2 秒后,按下(650, 650)的位置,暂停 2 秒,并抬起
TouchAction(driver).tap(x=650, y=650).perform()
time.sleep(2)
TouchAction(driver).press(x=650,y=650).wait(2000).release().perform()
长按操作
应用场景
模拟手指对元素或坐标的长按操作。比如,长按某个按钮弹出菜单。
方法名
# 模拟手指对元素或坐标的长按操作
# 参数:
# el:元素
# x:x坐标
# y:y坐标
# duration:长按时间,毫秒
TouchAction(driver).long_press(el=None, x=None, y=None, duration=1000).perform()
示例
使用坐标的形式点击 WLAN (650, 650),2 秒后,长按(650, 650)的位置持续 2 秒
TouchAction(driver).tap(x=400, y=400).perform()
time.sleep(2)
TouchAction(driver).long_press(x=400, y=400, duration=2000).release().perform()
移动操作
应用场景
模拟手指移动操作,比如,手势解锁需要先按下,再移动。
方法名
# 模拟手指对元素或坐标的移动操作
# 参数:
# el:元素
# x:x坐标
# y:y坐标
TouchAction(driver).move_to(el=None, x=None, y=None).perform()
例
在手势解锁中,画一个如下图的案例
包名界面名为 com.android.settings/.ChooseLockPattern
TouchAction(driver).press(x=246, y=857).move_to(x=721, y=867).move_to(x=1200, y=851).move_to(x=1200, y=1329).move_to(x=724, y=1329).move_to(x=246, y=1329).move_to(x=718, y=1815).release().perform()
手机操作API
获取手机分辨率
# 获取手机分辨率
driver.get_window_size()
手机截图
应用场景
有些自动化的操作可能没有反应,但并不报错。此时我们就可以将操作过后的关键情况,截图留存。后 期也可以根据图片发现问题。
方法名
# 获取手机分辨率
# 参数:
# filename:指定路径下,指定格式的图片
get_screenshot_as_file(filename)
示例
- 打开设置页面
- 截图当前页面保存到当前目录,命名为screen.png
driver.get_screenshot_as_file(os.getcwd() + os.sep + './screen.png')
执行效果
项目目录下会将设置页面保存成 screen.png
获取和设置手机网络
应用场景
视频应用在使用流量看视频的时候,大部分都会提示用户正在是否继续播放。作为测试人员,我们可能 需要用自动化的形式来判断是否有对应的提示。即,用流量的时候应该有提示,不用流量的时候应该没 有提示。
# 获取手机网络
driver.network_connection
# 设置手机网络
# 参数:
# connectionType:网络类型
driver.set_network_connection(connectionType)
示例
设置当前设备为飞行模式
driver.set_network_connection(1)
发送键到设备
应用场景
模拟按 “返回键” “home键” 等等操作,比如,很多应用有按两次返回键退出应用的功能,如果这个功能 需要我们做自动化,那么一定会用到这个方法
方法名
# 发送键到设备
# 参数:
# keycode:发送给设备的关键代码
# metastate:关于被发送的关键代码的元信息,一般为默认值
driver.press_keycode(keycode, metastate=None)
注意点
按键对应的编码,可以在百度搜索关键字 “android keycode”
例如:https://blog.csdn.net/feizhixuan46789/article/details/16801429
示例
点击三次音量加,再点击返回,再点击两次音量减。
driver.press_keycode(24) driver.press_keycode(24) driver.press_keycode(24) driver.press_keycode(4) driver.press_keycode(25) driver.press_keycode(25)
操作手机通知栏
应用场景
测试即时通信类软件的时候,如果 A 给 B 发送一条消息,B 的通知栏肯定会显示对应的消息。我们想通过通知栏来判断 B 是否收到消息,一定要先操作手机的通知栏
方法名
# 打开手机通知栏
driver.open_notifications()
注意点
appium官方并没有为我们提供关闭通知的api,那么现实生活中怎么关闭,就怎样操作就行,比如,手指从下往上滑动,或者,按返回键
示例
打开通知栏,两秒后,关闭通知栏
driver.open_notifications()
time.sleep(2)
driver.press_keycode(4)
eycode(24) driver.press_keycode(4) driver.press_keycode(25) driver.press_keycode(25)
### 操作手机通知栏
应用场景
测试即时通信类软件的时候,如果 A 给 B 发送一条消息,B 的通知栏肯定会显示对应的消息。我们想通过通知栏来判断 B 是否收到消息,一定要先操作手机的通知栏
方法名
打开手机通知栏
driver.open_notifications()
注意点
appium官方并没有为我们提供关闭通知的api,那么现实生活中怎么关闭,就怎样操作就行,比如,手指从下往上滑动,或者,按返回键
示例
打开通知栏,两秒后,关闭通知栏
driver.open_notifications()
time.sleep(2)
driver.press_keycode(4)