前置条件
Windows 10
loguru
HTMLTestRunner
最近将原有logging日志系统替换成了loguru,loguru的好处不用多说,简单好用。配置起来也比lgging方便多了。封装代码如下:
import time, os
from loguru import logger
from settings import LOG_DIR # 日志保存路径
class Log:
"""输出日志到文件和控制台"""
def __init__(self):
# 文件的命名
log_name = f"test_{time.strftime(‘%Y-%m-%d‘, time.localtime()).replace(‘-‘,‘_‘)}.log"
log_path = os.path.join(LOG_DIR, log_name)
# 判断日志文件夹是否存在,不存则创建
if not os.path.exists(LOG_DIR):
os.mkdir(LOG_DIR)
# 日志输出格式
formatter = "{time:YYYY-MM-DD HH:mm:ss} | {level}: {message}"
# 日志写入文件
logger.add(log_path, # 写入目录指定文件
format=formatter,
encoding=‘utf-8‘,
retention=‘10 days‘, # 设置历史保留时长
backtrace=True, # 回溯
diagnose=True, # 诊断
enqueue=True, # 异步写入
# rotation="5kb", # 切割,设置文件大小,rotation="12:00",rotation="1 week"
# filter="my_module" # 过滤模块
# compression="zip" # 文件压缩
)
def debug(self, msg):
logger.debug(msg)
def info(self, msg):
logger.info(msg)
def warning(self, msg):
logger.warning(msg)
def error(self, msg):
logger.error(msg)
log = Log()
将上述封装代码引入,生成的html仍没有日志。点击通过
无法查看日志。
原来使用HTMLTestRunner
生成html
测试报告时,报告中只有console
输出,logging
的输出无法保存,如果要在报告中加入每一个测试用例执行的日志信息,则需要改HTMLTestRunner
源码。
修改_TestResult
类,同时别忘了在文件最上面import logging
。
import logging
class _TestResult(TestResult):
# note: _TestResult is a pure representation of results.
# It lacks the output and reporting ability compares to unittest._TextTestResult.
def __init__(self, verbosity=1, retry=0,save_last_try=False):
TestResult.__init__(self)
self.stdout0 = None
self.stderr0 = None
self.success_count = 0
self.failure_count = 0
self.error_count = 0
self.skip_count = 0
self.verbosity = verbosity
# result is a list of result in 4 tuple
# (
# result code (0: success; 1: fail; 2: error;3:skip),
# TestCase object,
# Test output (byte string),
# stack trace,
# )
self.result = []
self.retry = retry
self.trys = 0
self.status = 0
self.save_last_try = save_last_try
self.outputBuffer = StringIO.StringIO()
self.logger = logging.getLogger() # 新增这一行
startTest
函数中初始化logging.Handler
def startTest(self, test):
# test.imgs = []
test.imgs = getattr(test, "imgs", [])
# TestResult.startTest(self, test)
self.outputBuffer.seek(0)
self.outputBuffer.truncate()
stdout_redirector.fp = self.outputBuffer
stderr_redirector.fp = self.outputBuffer
self.stdout0 = sys.stdout
self.stderr0 = sys.stderr
sys.stdout = stdout_redirector
sys.stderr = stderr_redirector
# 新增如下代码
self.log_cap = StringIO.StringIO()
self.ch = logging.StreamHandler(self.log_cap)
self.ch.setLevel(logging.DEBUG)
formatter = logging.Formatter(‘[%(levelname)s][%(asctime)s] [%(filename)s]->[%(funcName)s] line:%(lineno)d ---> %(message)s‘)
self.ch.setFormatter(formatter)
self.logger.addHandler(self.ch)
complete_output
函数的返回值中加入logging
存在内存中的输出,用换行符隔开
def complete_output(self):
"""
Disconnect output redirection and return buffer.
Safe to call multiple times.
"""
if self.stdout0:
sys.stdout = self.stdout0
sys.stderr = self.stderr0
self.stdout0 = None
self.stderr0 = None
# return self.outputBuffer.getvalue()
return self.outputBuffer.getvalue()+‘\n‘+self.log_cap.getvalue() # 新增这一行
每个用例执行完后,清除handler,修改stopTest函数
def stopTest(self, test):
# Usually one of addSuccess, addError or addFailure would have been called.
# But there are some path in unittest that would bypass this.
# We must disconnect stdout in stopTest(), which is guaranteed to be called.
if self.retry and self.retry>=1:
if self.status == 1:
self.trys += 1
if self.trys <= self.retry:
if self.save_last_try:
t = self.result.pop(-1)
if t[0]==1:
self.failure_count -=1
else:
self.error_count -= 1
test=copy.copy(test)
sys.stderr.write("Retesting... ")
sys.stderr.write(str(test))
sys.stderr.write(‘..%d \n‘ % self.trys)
doc = getattr(test,‘_testMethodDoc‘,u"") or u‘‘
if doc.find(‘_retry‘)!=-1:
doc = doc[:doc.find(‘_retry‘)]
desc ="%s_retry:%d" %(doc, self.trys)
if not PY3K:
if isinstance(desc, str):
desc = desc.decode("utf-8")
test._testMethodDoc = desc
test(self)
else:
self.status = 0
self.trys = 0
#self.complete_output()
a = self.complete_output()
# 清除log的handle,新增如下代码
self.logger.removeHandler(self.ch)
return a
可能各自用的HTMLTestRunner
版本内容不一样,均只需按照上述修改即可。
按照上述修改,再次运行,生成的html报告还是没有日志内容,会不会是loguru和logging不兼容?
上网苦苦找寻,终于找到了解决办法,再次修改loguru封装代码如下:
import time, os, logging
from loguru import logger
from settings import LOG_DIR # 日志保存路径
# 新增如下三行代码
class PropogateHandler(logging.Handler):
def emit(self, record):
logging.getLogger(record.name).handle(record)
class Log:
"""输出日志到文件和控制台"""
def __init__(self):
# 文件的命名
log_name = f"test_{time.strftime(‘%Y-%m-%d‘, time.localtime()).replace(‘-‘,‘_‘)}.log"
log_path = os.path.join(LOG_DIR, log_name)
# 判断日志文件夹是否存在,不存则创建
if not os.path.exists(LOG_DIR):
os.mkdir(LOG_DIR)
# 日志输出格式
formatter = "{time:YYYY-MM-DD HH:mm:ss} | {level}: {message}"
# 日志写入文件
logger.add(log_path, # 写入目录指定文件
format=formatter,
encoding=‘utf-8‘,
retention=‘10 days‘, # 设置历史保留时长
backtrace=True, # 回溯
diagnose=True, # 诊断
enqueue=True, # 异步写入
# rotation="5kb", # 切割,设置文件大小,rotation="12:00",rotation="1 week"
# filter="my_module" # 过滤模块
# compression="zip" # 文件压缩
)
# 新增代码
logger.add(PropogateHandler(), format=formatter)
def debug(self, msg):
logger.debug(msg)
def info(self, msg):
logger.info(msg)
def warning(self, msg):
logger.warning(msg)
def error(self, msg):
logger.error(msg)
log = Log()
HTMLTestRunner_loguru下html没有显示日志内容问题
原文:https://www.cnblogs.com/tahitimoon/p/15229214.html