|
2#
楼主 |
发表于 2018-4-13 14:00:52
|
只看该作者
当任一个id出现调整时,只要修改LoginPage这一个类的内容即可,维护成本降低。通过中文名字命名每个
控件,测试用例可读性增强。同时封装功能的方法,用例中只要调用方法即可,使得用例更加简洁,便于维护。
3. 尽量少用sleep
现在大多数的Web应用程序是使用Ajax技术。当一个页面被加载到浏览器时, 该页面内的元素可以
在不同的时间点被加载。这使得定位元素变得困难, 如果元素不再页面之中,会抛出 ElementNotVisibleEx
ception 异常。有的人使用sleep方法来等待页面加载成功,比如sleep(5),假入某一次运行网络不稳定,
页面加载了10秒才成功,那这个sleep就没用了。那你可以说我sleep(30)再进行下一步操作不就得了,
但是这样的话用例的执行时间变长了很多,对于手动执行没有什么优势了。
怎么减少sleep呢,有两个方法:
(1)WebDriverWait
使用selenium进行web自动化测试可以使用WebDriverWait方法,具体可google使用方法:
# 当页面元素可见后,表示页面加载成功
self.flag_frame = 'ui_ptlogin'
locator = (By.NAME, self.flag_frame)
WebDriverWait(self.driver, 20).until(EC.frame_to_be_available_and_switch_to_it(locator))
非web的UI自动化测试,可以自己设计一些waitForInvisiable之类的方法,等待控件加载成功。
(2)TimeOut方法增加重试逻辑
selenium执行下拉框选择时,有一定的概率会失败,在这里增加重试逻辑,会提升用例的稳定性,举一个重试逻辑的例子:
class Timeout(object):
'''Timeout类,实现超时重试逻辑'''
def __init__(self, timeout = 10, interval = 0.5):
'''
@param timeout:超时描述,默认是10
@param interval:重试时间间隔秒数,默认是0.5
'''
self.timeout = float(timeout)
self.interval = float(interval)
def retry(self, func, args, exceptions=(), resultmatcher=None, message=""):
"""多次尝试调用函数,成功则并返回调用结果,超时则抛出异常。
:param func: 尝试调用的函数
:type args: dict或tuple
:param args: func函数的参数
:type exceptions: tuple类型,tuple元素是异常类定义,如QPathError, 而不是异常实例,如QPathError()
:param exceptions: 调用func时抛出这些异常,则重试。
如果是空列表(),则不捕获异常。
:type resultmatcher: 函数指针类型
:param resultmatcher: 函数指针,用于验证第1个参数func的返回值。
默认值为None,表示不验证func的返回值,直接返回。
其函数原型为:
def result_match(ret): # 参数ret为func的返回值
pass
当result_match返回True时,直接返回,否则继续retry。
:return: 返回成功调用func的结果
"""
start = time.time()
waited = 0.0
try_count = 0
while True:
try:
try_count += 1
if dict == type(args):
ret = func(**args)
elif tuple == type(args):
ret = func(*args)
else:
raise Exception("args type %s is not a dict or tuple" % type(args))
if resultmatcher == None or resultmatcher(ret) == True:
print "%s Timeout尝试次数: " % message, try_count
TestLog.log_info("%s Timeout尝试次数: %s" % (message, str(try_count)))
return ret
except exceptions:
pass
waited = time.time() - start
if waited < self.timeout:
time.sleep(min(self.interval, self.timeout-waited))
elif try_count == 1:
continue
else:
raise Exception("在%d秒里尝试了%d次" % (self.timeout, try_count))
print try_count
4. 脚本中不使用坐标和图像识别
selenium对控件的找寻提供了很多方法,尽量通过id或者class_name来查找控件。但有一种情况是动
态布局条件的id都是一样的,无法区别。我的经验是通过text的方法查找:
driver.find_element_by_xpath("//*[text()='%s']" % string)
5. 保证用例的独立性
尽量保证一条测试用例只做一件事情,而且用例与用例之间没有关联关系,这样能提升用例的稳定性
6. 能不用UI的地方尽量不用UI操作
比如用例的目的是为了检查广告信息的展现功能,需要新建一条广告,通过界面新建广告特别繁杂,
可以通过API创建一条广告,再在界面上进行检查。这样就能化繁为简了。 |
|