高效自动化测试框架-优秀实践05-支持事件驱动模式
背景
通常测试用例都是线性的,不太能够满足用户操作的复杂场景,比如,循环操作,有背景呼叫或业务,分支操作,或者时间间隔等,所以相对的,针对于关键字驱动,这里引入事件驱动,这样子能够满足跟复杂的操作场景
事件驱动与关键字驱动对比
区别点 | 关键字驱动 | 事件驱动 |
---|---|---|
封装方法 | 一般封装成函数 | 一般封装成模块,以类为单位,可以提供各种属性 |
运行模式 | 一般是单线程 | 可以是多线程的,或者并发的 |
测试过程 | 一般在测试前就已经固定好流程,无法在线修改 | 执行过程中可以动态修改添加事件 |
使用场景 | 一般用于功能测试和部分系统测试 | 一般用于长时间测试,以及模拟用户的现场测试 |
其中一种设计方法
按照<高效自动化测试平台>,书籍第385页,提供了一种思路,分别设计,调度器,计划任务池,锁服务,数据暂存器,其中锁服务是为了解决资源竞争的问题
我的设计思路
借鉴之前在华为的工作经验,测试脚本中支持一下行为:
-
循环执行N次,直到成功
-
强制执行N次,不管是否成功
-
对于两个事件的组合,强制执行N次,直到其中一个成功
而书籍<高效自动化测试平台>中,还提到事件有可能还是以背景工作的方式存在,或者定时去执行的
这里,我并不打算完全借鉴<高效自动化测试平台>的编码思路,想要直接编写一个装饰器,用装饰器提供相关功能
相关代码
from core.logger.logger_interface import logger from functools import wraps from threading import Thread import time class Event: @classmethod def loop(cls, times): """ 被该装饰器装饰的函数,将会在未抛出异常的情况下,串行循环执行times次 :param times: 所要执行的事情的次数 :return: """ logger.info("正在调用Event.loop,在未抛异常的情况下,将会串行循环执行目标事件{}次".format(times)) def decorate(func): @wraps(func) def wrapper(*args, **kwargs): for i in range(times): func(*args, **kwargs) return wrapper return decorate @classmethod def loop_to_success(cls, times): """ 被该装饰器装饰的函数,将会在未抛出异常的情况下,串行循环执行times次 :param times: 所要执行的事情的次数 :return: """ logger.info("正在调用Event.loop,在未抛异常的情况下,将会串行循环执行目标事件{}次".format(times)) def decorate(func): @wraps(func) def wrapper(*args, **kwargs): success_flag = False for i in range(times): try: func(*args, **kwargs) success_flag = True except Exception as err: logger.info("正在调用Event.force,抛出异常,err为{}".format(err)) if success_flag: break return wrapper return decorate @classmethod def force(cls, times): """ 被该装饰器装饰的函数,将会在未抛出异常的情况下,串行循环执行times次 :param times: 所要执行的事情的次数 :return: """ logger.info("正在调用Event.force,不管是否抛出异常,都会会串行循环执行目标事件{}次".format(times)) def decorate(func): @wraps(func) def wrapper(*args, **kwargs): for i in range(times): try: func(*args, **kwargs) except Exception as err: logger.info("正在调用Event.force,抛出异常,err为{}".format(err)) return wrapper return decorate @classmethod def background(cls, times, delay=0.01): """ 被该装饰器装饰的函数将以多线程的方式执行times次,并且每两次操作之间间隔delay秒 :param delay: 事件执行的事件间隔 :param times: 所要执行的事情的次数 :return: """ # logger.info("正在调用Event.force,不管是否抛出异常,都会会串行循环执行目标事件{}次".format()) def decorate(func): @wraps(func) def wrapper(*args, **kwargs): def bg_func(): for i in range(times): func(*args, **kwargs) time.sleep(delay) t = Thread(target=bg_func) t.start() return wrapper return decorate if __name__ == "__main__": @Event.loop_to_success(5) def print_hello(): print("999") @Event.loop(50) def print_loop(): print("print_loop") time.sleep(1) @Event.force(50) def print_force(): print("print_force\n") time.sleep(1) @Event.background(100, 1) def print_background_info(): print("print_background_info\n") print_background_info() print_force()
待改进的地方
-
还未实现的功能,两个事件,只要其中一个成功即可的装饰器
参考博客地址: Selenium Grid 搭建及使用 - 磊磊落落