Selenium2Library源码解析与扩展(二)
来源:互联网 发布:mac 找不到原始项目 编辑:程序博客网 时间:2024/05/21 06:54
说明:下面说到的一些扩展也适用于AppiumLibrary。
_waiting.py
包括一些等待操作,常用来等待页面加载完成,如:
Input Text css=.username adminInput Text css=.password 123456Wait Until Page Contains Element css=.loginsuccess#Now [sleep] is not need Click Element link=xxxx
使用如上方法,即可不用使用sleep等待登录后页面加载,并能在第一时间点击’link=xxxx’元素。
wait_until_page_contains_element()实现如下:
def wait_until_page_contains_element(self, locator, timeout=None, error=None): """Waits until element specified with `locator` appears on current page. Fails if `timeout` expires before the element appears. """ if not error: error = "Element '%s' did not appear in <TIMEOUT>" % locator #这里通过_is_element_present()在设置超时范围内一直判断locator匹配元素出现 self._wait_until(timeout, error, self._is_element_present, locator)
_wait_until()实现如下:
def _wait_until(self, timeout, error, function, *args): error = error.replace('<TIMEOUT>', self._format_timeout(timeout)) def wait_func(): return None if function(*args) else error #不断执行function(*args)直到wait_func()返回None self._wait_until_no_error(timeout, wait_func)
然后就是_waiting.py的核心_wait_until_no_error()了,实现如下:
def _wait_until_no_error(self, timeout, wait_func, *args): #格式化输入的超时时间(从而支持'3s'、'1min'),如果为None,则读取默认配置 timeout = robot.utils.timestr_to_secs(timeout) if timeout is not None else self._timeout_in_secs maxtime = time.time() + timeout #死循环 while True: timeout_error = wait_func(*args) if not timeout_error: return #超时,抛出之前设置的error if time.time() > maxtime: raise AssertionError(timeout_error) time.sleep(0.2)
受此启发,在平常编写脚本一般会在每步操作加若干sleep延时,以增加脚本稳定性:
Click Element link=lkSleep 5sInput Text css=.input hello dasshSleep 5sClick Element css=.btn
当脚本长到一定程度时,使用sleep消耗的时间就非常可观了,扩展方法如下:
def _wait_until_no_error_fixed(self, timeout, fail_raise_error, message, wait_func, *args): timeout = robot.utils.timestr_to_secs(timeout) if timeout is not None else 15 maxtime = time.time() + timeout while True: try: res = wait_func(*args) except Exception, e: timeout_error = True else: timeout_error = False if not timeout_error: self._info(u"%s ==> PASS." % (message)) return res if time.time() > maxtime: if not fail_raise_error: self._info(u"%s ==> NOT PASS." % (message)) break else: raise AssertionError(u"%s ==> FAIL." % (message)) break time.sleep(0.5)
然后扩展click_element()、input_text()如下:
def input_until_no_error(self, locator, text, message="", timeout=None): """Try types the given `text` into text field identified by `locator` until no error occurred. Fails if `timeout` expires before the input success. """ if not message: message = "Typing text '%s' into text field '%s'" % (text, locator) self._wait_until_no_error_fixed(timeout, True, message, self.input_text, locator, text)def click_until_no_error(self, locator, message="", timeout=None): """Try click element identified by `locator` until no error occurred. Fails if `timeout` expires before the click success. """ if not message: message = "Clicking element '%s'" % locator self._wait_until_no_error_fixed(timeout, True, message, self.click_element, locator)
从而上面的脚本可以改为如下,实现元素一出现就立即操作:
Click Until No Error link=xxxxInput Until No Error css=.input hello dasshClick Until No Error css=.btn
第一节提到的几个方法扩展也可以再次扩展如下:
def select_window_until_no_error(self, locator, message="", timeout=None): """Try selects the window matching locator and return previous window handle until no error occurred. locator: any of name, title, url, window handle, excluded handle's list, or special words. """ if not message: message = "Selecting window '%s'" % locator self._wait_until_no_error_fixed(timeout, True, message, self.select_window, locator)def title_should_contain_in_time(self, title_piece_list, message="", timeout=None): """Verifies that current title contains `title_piece_list` in setting time. Fails if `timeout` expires before find page contains `title_piece_list`. """ if not isinstance(title_piece_list, list): piece_list = self._convert_to_list(title_piece_list) if not message: message = "Page title should contain '%s'" % (title_piece_list) self._wait_until_no_error_fixed(timeout, True, message, self.title_should_contain, *piece_list)def click_until_no_error_js(self, locator_css, message="", timeout=None): """Try JavaScript click element identified by `locator_css` until no error occurred. Fails if `timeout` expires before find page contains `title_piece_list`. """ if not message: message = "JavaScript clicking element '%s'" % locator_css self._wait_until_no_error_fixed(timeout, True, message, self.click_element_js, locator_css)
title_should_contain_in_time()因为要支持多个片段校验,与之前的title_should_contain()用法有些不一致,使用方法如下:
Title Should Contains 一下 百度 知道 你就Title Should Contains In Time 一下,百度,知道,你就Title Should Contains In Time [一下,百度,知道,你就] 【校验百度首页】 10s
有时候会遇到这种情况,开发在首页多了个弹出的活动窗,你不得把他X掉;或者进入app,提示有更新,为应对这种情况,扩展如下方法:
def click_if_exists_in_time(self, locator, message="", timeout=None): """Try click element identified by `locator` in setting time. Ignore if `timeout` expires before the click success. """ if not message: message = "Clicking element '%s'" % locator self._wait_until_no_error_fixed(timeout, False, message, self.click_element, locator)
当click的对象是链接时,一般会使用link=xxxx,但假如有2个link=xxxx元素,你想点击第2个,又不想换用其它方式定位;或者在app测试里,你会发现开发没有text,没有index给你定位,通过控件类型定位(这样只会匹配第一个元素),又不想写一长串xpath时,扩展如下方法:
def click_nth_element(self, locator, nth=1): """Click the nth element identified by `locator`.""" try: nth = int(nth) except ValueError, e: raise ValueError("'%s' is not a number" % (nth)) if nth <= 0: raise ValueError("'nth' must bigger then 0") elements = self.get_webelements(locator) self._info("Clicking %dth element '%s'" % (nth, locator)) elements[nth-1].click()def click_nth_until_no_error(self, locator, nth=1, message="", timeout=None): """Click the nth element identified by `locator` until no error occurred. Fails if `timeout` expires before the click success. """ if not message: message = "Clicking %sth element '%s'" % (nth, locator) self._wait_until_no_error_fixed(timeout, True, message, self.click_nth_element, locator, nth)
扩展校验内容、元素是否在页面上:
def page_should_contain_text_in_time(self, text, message="", timeout=None): """Verifies text is not found on the current page in setting time. Fails if `timeout` expires before find page contain text. """ if not message: message = "Page should have contained text '%s'" % (text) self._wait_until_no_error_fixed(timeout, True, message, self.page_should_contain, text, 'NONE')def page_should_contain_element_in_time(self, locator, message="", timeout=None): """Verifies element identified by `locator` is not found on the current page in setting time. Fails if `timeout` expires before find page contain locator element. """ if not message: message = "Page should have contained element '%s'" % (locator) self._wait_until_no_error_fixed(timeout, True, message, self.page_should_contain_element, locator, '', 'NONE')
注:上面这两个方法其实和_waiting.py自带wait_until_page_contains(),wait_until_page_contains_element()类似。
上传文件choose_file()要求路径为绝对路径,有时候不方便填绝对路径时(如部署脚本到Jenkins),扩展如下方法:
def choose_file_until_no_error(self, locator, file_path, message="", timeout=None): """Try inputs the `file_path` into file input field found by `locator` until no error occurred. Fails if `timeout` expires before the choose file success. """ file_path = file_path.encode("utf-8") if os.path.isabs(file_path) else os.path.join(os.getcwd(), file_path.encode("utf-8")) if not os.path.exists(file_path): raise ValueError("path file '%s' is not exists." % file_path) if not message: message = "Choosing file '%s' from button '%s'" % (file_path, locator) self._wait_until_no_error_fixed(timeout, True, message, self.choose_file, locator, file_path)
choose_file_until_no_error()判断路径是否为绝对路径,如果不是,则相对为os.getcwd()路径。
注: 路径中建议不含中文。
有时候会要获取匹配locator的个数,扩展如下方法:
def get_element_count(self, locator): """Count elements found by `locator`.""" return len(self.get_webelements(locator))def get_element_count_in_time(self, locator, message="", timeout=None): """Count elements found by `locator` until result is not 0. Return 0 if `timeout` expires. """ return self._wait_until_not_value(timeout, 0, False, message, self.get_element_count, locator)
get_element_count_in_time()主要是解决由于页面加载慢、异步请求未完成locator匹配为0个元素的情况。注意上面调用的是_wait_until_not_value(),而不是前面的_wait_until_no_error_fixed(),源码如下:
def _wait_until_not_value(self, timeout, value, fail_raise_error, message, wait_func, *args): timeout = robot.utils.timestr_to_secs(timeout) if timeout is not None else 15 maxtime = time.time() + timeout while True: res = wait_func(*args) if res != value: if message: self._info(u"%s ==> %s." % (message, res)) return res if time.time() > maxtime: if not fail_raise_error: if message: self._info(u"%s ==> %s." % (message, res)) return res if message: raise AssertionError(u"%s ==> %s." % (message, res)) else: raise AssertionError(u"Return ==> %s." % res) break time.sleep(0.5)
扩展包地址:
https://github.com/daassh/SeleniumExtend
使用方法:
不再导入Selenium2Library,而是导入此文件。
有些扩展包里的方法没讲请自行阅读或者RF里F5,至此这个系列结束→_→。
过段时间会整理出AppiumExtend.py扩展AppiumLibrary。
by dassh
- Selenium2Library源码解析与扩展(二)
- Selenium2Library源码解析与扩展(一)
- GeoServer源码解析和扩展 (二)注册服务
- GeoServer源码解析和扩展 (二)注册服务
- GeoServer源码解析和扩展 (二)注册服务
- GeoServer源码解析和扩展 (二)注册服务
- GeoServer源码解析和扩展 (二)注册服务
- GeoServer源码解析和扩展 (二)注册服务
- Selenium2Library源码解读(1)- 概述
- Selenium2Library源码解读(1)- _logging模块
- jquery源码分析与扩展二
- Selenium2Library与HttpLibrary.HTTP
- Android 源码环境搭建配置与问题解析(二)
- 【特征匹配】SURF原理与源码解析(二)
- 《Android源码设计模式解析与实战》读书笔记(二)
- Volley框架使用与源码解析(二)
- TLD(Tracking-Learning-Detection)算法学习与源码解析(二)之runtld.cpp源码解析
- AsyncTask使用与源码解析(二)
- LeetCode *** 216. Combination Sum III
- 将一个spine的骨骼绑定到另一个spine的骨骼上
- c++上机1.2
- ScrollView嵌套ListView——解决滑动冲突问题
- Linux系统的休眠与唤醒简介
- Selenium2Library源码解析与扩展(二)
- 《UNIX网络编程》例子程序中所使用的 包裹函数 及 部分常量
- mysql中的union all与union
- C++实验3-多分数段函数求值
- hdmi接口介绍
- 154. Find Minimum in Rotated Sorted Array II
- CentOS设置网卡成DHCP动态获取IP
- 关于手机号码合法性判断
- For语句去循环,Objective C 提供一个Block的遍历方法