如何解决UI自动化脚本不稳定原创
金蝶云社区-廖彬植
廖彬植
19人赞赏了该文章 2,757次浏览 未经作者许可,禁止转载编辑于2020年12月24日 09:17:30
summary-icon摘要由AI智能服务提供

文本介绍了在调试UI自动化代码时,经常遇到用例不稳定的问题,主要是由于selenium脚本稳定性不足。通过sleep或隐式等待会增加运行时间成本。文章推荐使用selenium的expected_conditions(EC)模块中的显式等待方法来解决此问题,详细说明了如何使用EC模块结合WebDriverWait来实现元素的等待校验,包括元素可见性、标题判断、元素是否存在等,并列举了多种使用场景和方法,以提高自动化脚本的稳定性和效率。

很多人调试UI自动化代码,很大概率会碰到用例不稳定的情况:有时候运行成功,有时候运行失败。失败的原因并非真的产品本身的功能有问题,而是可能因为某一元素在某一次运行时定位不到,可能是网络问题,可能是环境不稳定。归根结底,都是因为selenium脚本的稳定性不足。通常的解决方案就是加上sleep或者隐式等待(implicitly_wait),但过多的sleep和隐式等待,会大大延长用例的运行时间,增加调试的时间成本。车到山前必有路,船到桥头自然直,selenium中的expected_conditions模块详解(简称EC)为解决这个问题提供了便利,以下是介绍结合EC模块封装的显式等待方法,其他异常的校验也可以通过结合EC模块,比如判断元素是否存在,判断文本是否存在,判断元素是否可点击等。


def explicitly_waiting(self, by_way, locator):
    """
    在设置时间内,默认每隔一段时间检查一次当前页面元素是否存在,超过设置时间仍检测不到,则抛出异常
    :param by_way: 定位方式
    :param locator: 元素定位值
    :return:
    """
    try:
        WebDriverWait(self.driver, 20, 0.5).until(ec.visibility_of_element_located((by_way, locator)))
        logger.info('等待元素:(' + locator + ')已出现')
        return True
    except TimeoutException:
        logger.info('查找元素:(' + locator + ')超时')
        raise TimeoutException


该显式等待结合了EC模块中的ec.visibility_of_element_located,判断元素是否存在,结合WebDriverWait。整个方法的逻辑为:每隔0.5秒检测元素是否存在,如果存在,则继续执行脚本,不再等待。如果检测元素不存在,在0.5秒后继续检测,在等待总时长20秒后,如果元素仍没有检测到,则抛出异常。


EC模块非常方便我们去校验selenium定位中存在的异常情况,以下是EC模块结合WebDriverWait的相关介绍,如果想深入了解,建议详细阅读EC模块相关介绍。


'''判断title是否是一致,返回布尔值'''

WebDriverWait(driver,10,0.1).until(EC.title_is("title_text"))


'''判断title是否与包含预期值,返回布尔值'''

WebDriverWait(driver,10,0.1).until(EC.title_contains("title_text"))


'''判断某个元素是否被加到了dom树里,并不代表该元素一定可见,如果定位到就返回元素'''

WebDriverWait(driver,10,0.1).until(EC.presence_of_element_located((locator)))


'''判断某个元素是否被添加到了dom里并且可见,可见代表元素可显示且宽和高都大于0'''

WebDriverWait(driver,10,0.1).until(EC.visibility_of_element_located((locator)))


'''判断元素是否可见,如果可见就返回这个元素'''

WebDriverWait(driver,10,0.1).until(EC.visibility_of(driver.find_element(locator)))


'''判断是否至少有1个元素存在于dom树中,如果定位到就返回列表'''

WebDriverWait(driver,10,0.1).until(EC.presence_of_all_elements_located((locator)))


'''判断是否至少有一个元素在页面中可见,如果定位到就返回列表'''

WebDriverWait(driver,10,0.1).until(EC.visibility_of_any_elements_located((locator)))


'''判断指定的元素中是否包含了预期的字符串,返回布尔值'''

WebDriverWait(driver,10,0.1).until(EC.text_to_be_present_in_element((locator),'预期的text'))


'''判断指定元素的value属性值中是否包含了预期的字符串,返回布尔值(注意:只是value属性)'''

WebDriverWait(driver,10,0.1).until(EC.text_to_be_present_in_element_value((locator),'预期的text'))


'''判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False'''

WebDriverWait(driver,10,0.1).until(EC.frame_to_be_available_and_switch_to_it(locator))


'''判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素'''

WebDriverWait(driver,10,0.1).until(EC.invisibility_of_element_located((locator)))


'''判断某个元素是否可见并且是可点击的,如果是的就返回这个元素,否则返回False'''

WebDriverWait(driver,10,0.1).until(EC.element_to_be_clickable((locator)))


'''等待某个元素从dom树中移除'''

WebDriverWait(driver,10,0.1).until(EC.staleness_of(driver.find_element(locator)))


'''判断某个元素是否被选中了,一般用在下拉列表'''

WebDriverWait(driver,10,0.1).until(EC.element_to_be_selected(driver.find_element(locator)))


'''判断某个元素的选中状态是否符合预期'''

WebDriverWait(driver,10,0.1).until(EC.element_selection_state_to_be(driver.find_element(locator),True))


'''判断某个元素的选中状态是否符合预期'''

WebDriverWait(driver,10,0.1).until(EC.element_located_selection_state_to_be((locator),True))


'''判断页面上是否存在alert,如果有就切换到alert并返回alert的内容'''

accept = WebDriverWait(driver,10,0.1).until(EC.alert_is_present())


总结不易,且看且点赞 【emoji】

赞 19