import datetime
import logging
import requests
#获取日志记录器、配置日志等级
logger = logging.getLogger(__name__)
logger.setLevel("DEBUG")
#默认日志格式
formatter = logging.Formatter("%(asctime)s - [%(levelname)s] - %(message)s")
#输出到控制台的handler
chlr = logging.StreamHandler()
#配置默认日志格式
chlr.setFormatter(formatter)
#日志记录器增加此handler
logger.addHandler(chlr)
def log(func):
"""
日志装饰器、简单记录函数的日志
:param func: 函数
:return:
"""
def inner(*args,**kwargs):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
res = func(*args,**kwargs)
logger.debug(f"func: {func.__name__}{args}->{res}")
return res
return inner
@log
def cms_login(userAccount=None,loginPwd=None):
url = "http://cms.duoceshi.cn/cms/manage/loginJump.do?userAccount="+userAccount+"&"+"loginPwd"+"="+str(loginPwd)
response = requests.get(url)
return (response.json())
cms_login("admin",123456)
import logging
from logging import handlers
from typing import Text
import colorlog
from common.setting import ConfigHandler
class LogHandler:
""" 日志打印封装"""
# 日志级别关系映射
level_relations = {
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL
}
def __init__(
self,
filename: Text,
level: Text = "info",
when: Text = "D",
fmt: Text = "%(levelname)-8s%(asctime)s%(name)s:%(filename)s:%(lineno)d %(message)s"
):
self.logger = logging.getLogger(filename)
formatter = self.log_color()
# 设置日志格式
format_str = logging.Formatter(fmt)
# 设置日志级别
self.logger.setLevel(self.level_relations.get(level))
# 往屏幕上输出
screen_output = logging.StreamHandler()
# 设置屏幕上显示的格式
screen_output.setFormatter(formatter)
# 往文件里写入#指定间隔时间自动生成文件的处理器
time_rotating = handlers.TimedRotatingFileHandler(
filename=filename,
when=when,
backupCount=3,
encoding='utf-8'
)
# 设置文件里写入的格式
time_rotating.setFormatter(format_str)
# 把对象加到logger里
self.logger.addHandler(screen_output)
self.logger.addHandler(time_rotating)
self.log_path = ConfigHandler.log_path
@classmethod
def log_color(cls):
""" 设置日志颜色 """
log_colors_config = {
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}
formatter = colorlog.ColoredFormatter(
'%(log_color)s[%(asctime)s] [%(name)s] [%(levelname)s]: %(message)s',
log_colors=log_colors_config
)
return formatter
INFO = LogHandler(ConfigHandler.info_log_path, level='info')
ERROR = LogHandler(ConfigHandler.error_log_path, level='error')
WARNING = LogHandler(ConfigHandler.warning_log_path, level='warning')
if __name__ == '__main__':
ERROR.logger.error("测试")
"""
日志装饰器,控制程序日志输入,默认为 True
如设置 False,则程序不会打印日志
"""
from functools import wraps
from utils.logging_tool.log_control import INFO, ERROR
def log_decorator(switch: bool):
"""
封装日志装饰器, 打印请求信息
:param switch: 定义日志开关
:return:
"""
def decorator(func):
@wraps(func)
def swapper(*args, **kwargs):
# 判断日志为开启状态,才打印日志
res = func(*args, **kwargs)
# 判断日志开关为开启状态
if switch:
_log_msg = f"\n======================================================\n" \
f"用例标题: {res['detail']}\n" \
f"请求路径: {res['url']}\n" \
f"请求方式: {res['method']}\n" \
f"请求头: {res['headers']}\n" \
f"请求内容: {res['request_body']}\n" \
f"接口响应内容: {res['response_data']}\n" \
f"接口响应时长: {res['res_time']} ms\n" \
f"Http状态码: {res['status_code']}\n" \
"====================================================="
_is_run = res['is_run']
# 判断正常打印的日志,控制台输出绿色
if _is_run in (True, None) and res['status_code'] == 200:
INFO.logger.info(_log_msg)
else:
# 失败的用例,控制台打印红色
ERROR.logger.error(_log_msg)
return res
return swapper
return decorator
"""
统计请求运行时长装饰器,如请求响应时间超时
程序中会输入红色日志,提示时间 http 请求超时,默认时长为 3000ms
"""
from utils.logging_tool.log_control import ERROR
def execution_duration(number: int):
"""
封装统计函数执行时间装饰器
:param number: 函数预计运行时长
:return:
"""
def decorator(func):
def swapper(*args, **kwargs):
res = func(*args, **kwargs)
run_time = res['res_time']
# 计算时间戳毫米级别,如果时间大于number,则打印 函数名称 和运行时间
if run_time > number:
ERROR.logger.error(
"\n==============================================\n"
"测试用例执行时间较长,请关注.\n"
"函数运行时间: %s ms\n"
"测试用例相关数据: %s\n"
"================================================="
, run_time, res)
return res
return swapper
return decorator
import logging
import os
from testlib.common.MyConfigParser import conf
from testlib.common.pathOperation import LOG_DIR
# 获取配置信息
level = conf.get_str("logging", "level")
f_level = conf.get_str("logging", "f_level")
s_level = conf.get_str("logging", "s_level")
filename = conf.get_str("logging", "filename")
# 获取日志文件路径
file_path = os.path.join(LOG_DIR, filename)
class Log:
@staticmethod
def log_collection():
"""日志收集器"""
# 创建日志收集器
log = logging.getLogger()
# 设置日志收集器等级
log.setLevel(level)
"""控制台输出"""
# 添加输出渠道
sh = logging.StreamHandler()
# 设置输出等级
sh.setLevel(s_level)
# 将输出渠道绑定在日志收集器上
log.addHandler(sh)
"""日志输出"""
# 添加输出渠道
fh = logging.FileHandler(file_path, encoding="utf8")
# 设置输出等级
fh.setLevel(f_level)
# 设置日志输出格式
formatter = logging.Formatter('%(asctime)s-%(levelname)s: %(message)s')
# 输出渠道和输出格式绑定
fh.setFormatter(formatter)
# 输出渠道和日志收集器绑定
log.addHandler(fh)
return log
log = Log.log_collection()
if __name__ == '__main__':
log = Log.log_collection()
res= log.info("DEBUE")
print(res)
# coding:utf-8
import logging,time,os
# 这个是日志保存本地的路径
root_path = os.path.dirname(__file__)
app_path = os.path.join(root_path, "resultReport/").replace("\\", "/")
log_path = app_path
class Log:
def __init__(self):
# 文件的命名
self.logname = os.path.join(log_path, '%s.log'%time.strftime('%Y_%m_%d'))
self.logger = logging.getLogger()
self.logger.setLevel(logging.DEBUG)
# 日志输出格式
self.formatter = logging.Formatter('[%(asctime)s] - %(filename)s[line:%(lineno)d] - fuc:%(funcName)s- %(levelname)s: %(message)s')
def __console(self, level, message):
# 创建一个FileHandler,用于写到本地
fh = logging.FileHandler(self.logname, 'a') # 追加模式
fh.setLevel(logging.DEBUG)
fh.setFormatter(self.formatter)
self.logger.addHandler(fh)
# 创建一个StreamHandler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(self.formatter)
self.logger.addHandler(ch)
if level == 'info':
self.logger.info(message)
elif level == 'debug':
self.logger.debug(message)
elif level == 'warning':
self.logger.warning(message)
elif level == 'error':
self.logger.error(message)
# 这两行代码是为了避免日志输出重复问题
self.logger.removeHandler(ch)
self.logger.removeHandler(fh)
# 关闭打开的文件
fh.close()
def debug(self, message):
self.__console('debug', message)
def info(self, message):
self.__console('info', message)
def warning(self, message):
self.__console('warning', message)
def error(self, message):
self.__console('error', message)
if __name__ == "__main__":
log = Log()
log.info("---测试开始----")
log.info("输入密码")
log.warning("----测试结束----")
import logging, time, os
BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
# 定义日志文件路径
LOG_PATH = os.path.join(BASE_PATH, "log")
if not os.path.exists(LOG_PATH):
os.mkdir(LOG_PATH)
class Logger():
def __init__(self):
self.logname = os.path.join(LOG_PATH, "{}.log".format(time.strftime("%Y%m%d")))
self.logger = logging.getLogger("log")
self.logger.setLevel(logging.DEBUG)
self.formater = logging.Formatter(
'[%(asctime)s][%(filename)s %(lineno)d][%(levelname)s]: %(message)s')
self.filelogger = logging.FileHandler(self.logname, mode='a', encoding="UTF-8")
self.console = logging.StreamHandler()
self.console.setLevel(logging.DEBUG)
self.filelogger.setLevel(logging.DEBUG)
self.filelogger.setFormatter(self.formater)
self.console.setFormatter(self.formater)
self.logger.addHandler(self.filelogger)
self.logger.addHandler(self.console)
logger = Logger().logger
if __name__ == '__main__':
logger.info("---测试开始---")
logger.debug("---测试结束---")