Selenium自动化测试的显示等待

打印 上一主题 下一主题

主题 575|帖子 575|积分 1725

在进行UI自动化测试的时候,我们为了保持用例的稳定性,往往要设置显示等待,显示等待就是说明确的要等到某个元素的出现或者元素的某些条件出现,比如可点击、可见等条件,如果在规定的时间之内都没有找到,那么就会抛出Exception.

上面是我用selenium写的一个测试用例,展示了selenium中显示等待的利用方式,其中会利用到expected_conditions模块和WebDriverWait类,注意这里expected_conditions是一个py文件的文件名,也就是一个模块名,这个模块下面有很多的条件类,而我们用例中利用的title_is就是一个条件类。
WebDriverWait是一个类,这个类的作用就是根据肯定的条件,不断的查抄这个条件是否被满足了。WebDriverWait类只有两个方法,一个是until直到满足某个条件,另一个是until_not直到不满足某个条件。
  1. class WebDriverWait(object):
  2. def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
复制代码
WebDriverWait有四个参数分别是,driver驱动, timeout超时时间, poll_frequency=POLL_FREQUENCY轮训时间,也就是去判断条件是否满足的时间间隔,默认是0.5秒, ignored_exceptions=None在等待的过程中必要忽略的异常,是一个可迭代的异常类聚集,比如我们可以设置一个list,内里是[NoSuchElementException,NoSuchAttributeException,InvalidElementStateException....],默认环境下,是一个元组,只包含一个NoSuchElementException,因为只有元素出现,才能去判断条件是否满足,在不断轮训的过程中,肯定会发生NoSuchElementException,这个时候必须忽略掉这个异常,不然步伐就会停止。
其中driver和timeout是毕传的位置参数,别的两个是选择传递的关键字参数,如果不传都有指定的默认值。
下面就进入我们本日的主题,selenium中的等待条件的讨论
等待条件

条件类的实现原理

在selenium.webdriver.support.expected_conditions这个模块里,存放着全部的等待条件,每个条件类的结构都是一样的一个__init__构造方法和一个__call__方法。
在python中,如果想把范例的对象当做函数来利用,那么就可以给这个类实现__call__方法,如下:
  1. class TestCase:
  2. def __init__(self):
  3. self.driver = webdriver.Chrome(executable_path="./driver/chromedriver")
  4. self.driver.get('http://www.baidu.com')
  5. # sleep(2)
  6. def __call__(self):
  7. print(self.driver.title)
  8. if __name__ == '__main__':
  9. case = TestCase()
  10. case()
复制代码
case()对象的调用,就会实行__call__方法内里的逻辑打印当前页面的标题,我们取一个selenium的实现类:
  1. class presence_of_element_located(object):
  2. def __init__(self, locator):
  3. self.locator = locator
  4. def __call__(self, driver):
  5. return _find_element(driver, self.locator)
复制代码
这个条件类的意思是判断一个元素是否已经渲染到页面当中,在利用这个条件的时候必要先实例化,传入元素的定位,然后要进行判断的时候必要对实例对象进行调用并传入driver,对实例对象进行调用的时候就会实行__call__方法里的条件判断逻辑。
WebDriverWait是如何进行条件判断的

再回到文章开头看一下我们利用显示等待的代码:
  1. wait = WebDriverWait(self.driver, 2)
  2. wait.until(EC.title_is('百度一下,你就知道'))
复制代码
先是实例化一个WebDriverWait对象,然后再调用until方法而且传递一个条件的实例对象,until方法里就会不断的去轮训条件是否满足。
  1. def until(self, method, message=''):
  2. screen = None
  3. stacktrace = None
  4. end_time = time.time() + self._timeout
  5. while True:
  6. try:
  7. value = method(self._driver)
  8. if value:
  9. return value
  10. except self._ignored_exceptions as exc:
  11. screen = getattr(exc, 'screen', None)
  12. stacktrace = getattr(exc, 'stacktrace', None)
  13. time.sleep(self._poll)
  14. if time.time() > end_time:
  15. break
  16. raise TimeoutException(message, screen, stacktrace)
复制代码

method这个参数就是我们传递进来的条件的实例对象,value = method(self._driver)这里就是进行对象的调用,也就是实行了__call__方法里的逻辑。
selenium里都有哪些条件



  • title_is 判断title是否出现
  • title_contains 判断title页面标题是否包含某些字符
  • presence_of_element_located 判断某个元素是否被加载到了dom树里,但是并不代表这个元素可见
  • url_contains 判断当前url是否包含某个url
  • url_matches 判断当前url是否符合某种格式
  • url_to_be 判断当前url是否出现
  • url_changes 判断当前url是否已经发生了变化
  • visibility_of_element_located 判断某个元素是否被添加到了dom树里,且宽高都大于0
  • visibility_of 判断看某个元素是否可见
  • presence_of_all_elements_located 判断至少有一个元素存在于dom树中,返回全部定位到的元素
  • visibility_of_any_elements_located 判断至少有一个元素在页面中可见
  • visibility_of_all_elements_located 判断是否全部元素都在页面中可见
  • text_to_be_present_in_element 判断指定的元素中是否包含了预期的字符串
  • text_to_be_present_in_element_value 判断指定的元素属性值中是否包含了预期的字符串
  • frame_to_be_available_and_switch_to_it 判断iframe是否可以switch进去
  • invisibility_of_element_located 判断某个元素是否在dom中不可见
  • element_to_be_clickable 判断某个元素是否可见而且是enable的,也就是说是是否可以点击
  • staleness_of 等待某个元素从dom中删除
  • element_to_be_selected 判断某个元素是否被选中了,一般用于下拉列表中
  • element_located_to_be_selected 与上面的意思一样,只不过上面实例化的时候传入的是元素对象,这个传入的是定位
  • element_selection_state_to_be 判断某个元素的选中状态是否符合预期
  • element_located_selection_state_to_be 与上面一样,只不过传值不同而已
  • number_of_windows_to_be 判断当前窗口数是否即是预期
  • new_window_is_opened 判断是否有窗口增长
  • alert_is_present 判断页面是否有弹窗
以上就是selenium支持的全部条件。
然后就是自定义了

说了那么多条件,实在我们也可以自己实现一个条件类,
  1. class page_is_load:
  2. def __init__(self, expected_title, expected_url):
  3. self.expected_title = expected_title
  4. self.expected_url = expected_url
  5. def __call__(self, driver):
  6. is_title_correct = driver.title == self.expected_title
  7. is_url_correct = driver.current_url == self.expected_url
  8. return is_title_correct and is_url_correct
复制代码
上面是自己实现的一个条件类,根据页面的url和标题来判断页面是否被正确加载,
  1. class TestCase:
  2. def __init__(self):
  3. self.driver = webdriver.Chrome(executable_path="./driver/chromedriver")
  4. self.driver.get('http://www.baidu.com/')
  5. # sleep(2)
  6. def __call__(self):
  7. print(self.driver.title)
  8. def test_wait(self):
  9. wait = WebDriverWait(self.driver, 2)
  10. wait.until(page_is_load("百度一下,你就知道", "http://www.baidu.com/"))
复制代码
最后感谢每一个认真阅读我文章的人,投桃报李总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:


这些资料,对于【软件测试】的朋侪来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能资助到你!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

道家人

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表