简介
添加等待是为了确保自动化脚本在执行过程中与应用程序之间的同步和稳定性。
应用程序的响应时间是不确定的,可能存在网络延迟、加载时间、动画效果等因素。如果在执行自动化脚本时没有适当的等待机制,脚本可能会在应用程序还未完成相应操作或加载完成之前继续执行下一步,导致测试失败或产生不稳定的结果。
通过添加适当的等待操作,可以使脚本在关键操作后等待一段时间,以确保应用程序完成相关任务或操作。这可以包括显式等待(例如等待特定元素出现、消失或可点击),或隐式等待(在整个脚本执行过程中设置一个全局的等待时间)。
等待操作有助于提高脚本的稳定性,减少因应用程序响应不一致而导致的测试失败。它还能够模拟用户在与应用程序交互时的真实等待时间,提供更真实的测试场景。
因此,在编写自动化脚本时,考虑添加适当的等待操作是一个重要的实践,可以提高脚本的可靠性和稳定性,并确保脚本与应用程序之间的同步。
强制等待
- 解决方案:在报错的元素操作之前添加等待。
- 原理:线程休眠一定时间。
time.sleep(3)
import time
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
class TestWait:
def setup_class(self):
'''
完成 capability 设置
初始化 driver
:return:
'''
# 设置 cpability
caps = {
# 设置 app 安装的平台(Android,iOS)
"platformName": "Android",
# 设置 appium 驱动
"appium:automationName": "uiautomator2",
# 设置设备名称
"appium:deviceName": "emulator-5554",
# 设置被测 app 的包名
"appium:appPackage": "io.appium.android.apis",
# 设置被测 app 启动页面的 Activity
"appium:appActivity": ".ApiDemos",
# 不清空缓存信息
"appium:noReset": True,
# 首次启动的时候,不停止app
"appium:dontStopAppOnReset": True,
# 跳过安装,权限设置等操作
"appium:skipDeviceInitialization": True,
}
# 初始化 driver
self.driver = webdriver.Remote(
"http://127.0.0.1:4723",
options=UiAutomator2Options().load_capabilities(caps)
)
def teardown_class(self):
'''
关闭 driver
:return:
'''
self.driver.quit()
def test_wait(self):
'''
点击 OS 按钮后等待 3 秒
输入框输入内容后等待 2 秒
点击返回按钮后等待 2 秒
:return:
'''
# 测试步骤
# 找到 OS 元素
el5 = self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="OS")
# 点击 OS 元素
el5.click()
# 等待 3 秒
time.sleep(3)
# 找到 Morse Code 元素
el6 = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Morse Code")
el6.click()
# 找到输入框元素
el7 = self.driver.find_element(AppiumBy.ID, "io.appium.android.apis:id/text")
# 在输入框中输入内容
el7.send_keys("ceshiren.com")
# 等待 2 秒
time.sleep(2)
# 点击返回按钮
self.driver.back()
# 等待 2 秒
time.sleep(2)
# 点击返回按钮
self.driver.back()
# 断言:判断首页中第一个元素的文本内容是 Access'ibility
result = self.driver.find_element(
AppiumBy.XPATH,
"//*[@resource-id='android:id/text1'][1]"
)
print(result.text)
assert result.text == "Access'ibility"
隐式等待
- 问题:难以确定元素加载的具体等待时间。
- 解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。
- 演练环境:雪球 app。
- 原理:隐式等待是一种全局的等待方式,设置一个等待时间,轮询查找(默认 0.5 秒)元素是否出现,如果没出现就抛出异常。
#设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常
driver.implicitly_wait(3)
隐式等待无法解决的问题
- 元素可以找到,使用点击等操作,出现报错。
原因:
- 页面元素加载是异步加载过程,通常 xml 会先加载完成,相应的元素属性后加载。
- 元素存在与否是由 xml 决定,元素的交互是由属性决定。
- 隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互。
解决方案:使用显式等待。
显式等待基本使用
- 示例:WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)。
- 原理:在最长等待时间内,轮询,是否满足结束条件。
- 注意:在初级时期,先关注使用。
# 显示等待 Morse Code 元素可点击
WebDriverWait(self.driver, 10).until(
expected_conditions.element_to_be_clickable(
(AppiumBy.ACCESSIBILITY_ID, "Morse Code")))
# 找到 Morse Code 元素
el6 = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Morse Code")
el6.click()
总结
Appium 提供了三种等待方式,确保测试脚本在执行时与应用程序状态同步。这些等待分为强制等待、隐式等待和显式等待三种。用户可以根据不同的需求结合使用这些等待方式,以提高测试脚本的稳定性和可靠性。