appium显示等待和隐式等待
编写测试用例的时候,由于页面渲染速度和系统处理逻辑的问题,免不了要使用一些等待机制。driver执行查找点击命令的速度是很快的,而框架本身又没有什么超时时间处理,所以如果不加入等待机制的话就会导致很多不必要的用例失败。其中最简单快捷粗暴的方式就是sleep,在python中这是一个系统级别的time库提供的方法,可以通过导入这个库使用该方法。sleep(时间/s) 它的原理就是线程等待,这个方法会强制休眠线程达到等待的效果。
虽然sleep简单好用,但是如果整个测试中贯穿了这种粗暴的等待方式,那用例也会变得十分缓慢并且不够优雅,于是出现了隐式等待和显示等待。怎么理解隐式和显示呢?前者是无差别等待,比如一个方法中声明了隐式等待 self.driver.implicitly_wait(10),那方法中所有的driver元素操作都会默认等待10秒,10秒还是找不到对应元素就会报错,而10秒内一旦找到就会立即向下执行。
def implicitly_wait(self, time_to_wait) -> None: """ Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session. To set the timeout for calls to execute_async_script, see set_script_timeout. :Args: - time_to_wait: Amount of time to wait (in seconds) :Usage: :: driver.implicitly_wait(30) """ self.execute(Command.SET_TIMEOUTS, { 'implicit': int(float(time_to_wait) * 1000)})
隐式等待实际就是发送了一段timeout的session给web driver,time_to_wait的值就是等待时间,由于这里乘了1000,所以它的单位是秒。隐式等待适用于需要等待所有元素可见或不可见的情况,并且等待时间相对固定;
而显式等待适用于需要等待特定元素状态满足特定条件的情况,并且等待时间可以根据不同的条件进行灵活设置。显示等待
from appium.webdriver.common.appiumby import AppiumBy from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWait WebDriverWait(self.driver, 20)\ .until/until_not(expected_conditions.visibility_of_element_located(AppiumBy.ID, "phone-number"))
显示等待原理是使用WebDriverWait 类中提供的方法,找到关键的until源码进行分析就能发现:
def until(self, method, message=''): """Calls the method provided with the driver as an argument until the \ return value does not evaluate to ``False``. :param method: callable(WebDriver) :param message: optional message for :exc:`TimeoutException` :returns: the result of the last call to `method` :raises: :exc:`selenium.common.exceptions.TimeoutException` if timeout occurs """ screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except InvalidSelectorException as e: raise e except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace)
等待元素满足条件,而until_not就是等待元素不满足条件,这个判断条件是引入了from selenium.webdriver.support import expected_conditions,里面包含了丰富的判断条件,包括但是不限于标题、URL、元素可见性、元素是否被选中等。在显示等待中,等待时间只对当前操作起作用,在超时时间内,while True循环会不断重试判断条件。