全自动日志——funnylog
背景
基于 YouQu
自动化测试框架操作方法封装写法,通常是这样的:类里面一个函数只包含一个操作或多次调用的一系列可合并的操作;
传统的日志输出方式,需要在每个函数里面主动编写日志输出代码 ,例如:
class XXXWidget:
def click_xxx(self):
"""点击某个元素"""
logger.info("点击某个元素")
...
# 省略代码部分
一个函数里面至少包含一条日志信息,如果比较复杂操作步骤,可能包含多条日志信息;
一个应用含有大量的操作函数,也就是说我们需要写大量的日志代码;
通过经验观察,我们发现,函数说明以及函数操作日志,具有较高的重复度(从上面的例子也可以看出来),因此我们大胆的设想,能不能基于框架执行时,自动的将函数说明作为日志打印出来,从而减少大量日志代码量和重复编写,那真是妙啊~。
基于此“天真”的想法,我们设计出了 YouQu
的日志系统。
实现原理
核心原理:
通过给类加上一个装饰器 @log
,动态给该类下所有的函数及父类函数添加日志装饰器 @_trace
,在此装饰器中我们能动态的捕获所调用函数的功能说明(func.__doc__
),通过日志输出器将其输出即可。
实现步骤:
- 通过
inspect.getmembers
获取被装饰的类下所有函数,包含静态方法,类方法,实例方法; - 通过
setattr(类, 方法, _trace)
的方式,给符合条件的函数,动态添加日志装饰器;
日志配置
[log_cli]
;日志相关配置(不打印构造函数和魔法函数的功能说明)
;批量执行时,终端输出的日志级别 DEBUG/INFO/ERROR
LOG_LEVEL = INFO
# ============= 自动输出日志的配置 ================
;支持类名以 xxx 开头的,自动将函数说明打印为日志, 多个参数以逗号隔开
CLASS_NAME_STARTSWITH = Assert
;支持类名以 xxx 结尾的,自动将函数说明打印为日志,多个参数以逗号隔开
CLASS_NAME_ENDSWITH = Widget
;支持类名包含 xxx 的,自动将函数说明打印为日志,多个参数以逗号隔开
CLASS_NAME_CONTAIN = ShortCut
# ==============================================
使用方法
在应用库 widget
方法库里面,只需要在出口文件加上类装饰器,就可以实现自动输出日志了;
# dfm_widget.py
from src import log
@log
class DfmWidget():
"""文管方法库出口"""
def click_xxx(self):
"""点击某个元素"""
注意,是类装饰器。
实例:
# dfm_widget.py
from src import log
@log
class DfmWidget():
"""文管方法库出口"""
@classmethod
def find_dfm_image(cls, *elements, multiple=False, rate=0.9):
"""
查找图片 {{elements}}.png 在屏幕中相似度大于 {{rate}} 的坐标
:param elements:
:param multiple:
:return:
"""
element = tuple(map(lambda x: f"{Config.PIC_RES_PATH}/{x}", elements))
return cls.find_image(*element, multiple=multiple)
调用方法时:
DfmWidget.find_dfm_image("dfm_001")
自动输出的日志:
>> x86_64-uos-6: 02/28 17:48:47 | INFO | logger_utils: [find_dfm_image]: 查找图片 dfm_001.png 在屏幕中相似度大于 0.9 的坐标
加上装饰器 @log
之后,方法层所有的函数(包括实例方法、类方法、静态方法)都不需要再写日志代码,执行的时候会自动输出,并且所有调用的方法会以 allure.step
的方式,展示在 allure 报告中,在报告中更能一目了然的看到用例执行步骤。
【日志模板语法】
通过观察前面的例子,细心的同学可能还发现了一个小细节:函数功能说明中,两对大括号中的内容 作为变量输出出来了;
没错,这就是我们参考Django
和 jinja2
的模板语法设计出的日志模板语法,使用方法很简单,用两对大括号把函数的参数括起来,这样在日志输出的时候就能把调用函数时参数的值输出出来。