我如何搭建自动化测试框架_02日志
参考https://blog.csdn.net/huilan_same/article/details/76572411该博客.
背景
在上一个博客中,写了如何去写一个基本的测试用例,并且把相关的参数给抽离出来,在这一节要继续去完善,那就是把日志的功能添加进去,既然是去打日志的话,name我们要提出我们的诉求
a.希望在日志中能够打印的信息有,时间,谁打印的日志,日志级别,日志内容
b.可以设置日志打印的界别
c.不同的日志,支持使用不用的颜色来打印
那么直接上代码
import os
import logging
from logging.handlers import TimedRotatingFileHandler
from utils.config import LOG_PATH
import time
class Logger(logging.Logger):
def __init__(self):
super().__init__("")
self.log_file_name = "test.log"
#TODO 这里要去判断,如果没有该目录和文件的话,则需要开始创建开日志文件
#TODO 这里的话,需要去获取脚本中的信息,然后用脚本信息中的case_ID作为日志名字,并且根据目录层级以及时间关系来创建目录
self.backup_count = 5
self.info_color = "\033[0;29m%s\033[0m"
self.msg_color = "\033[0;36m%s\033[0m"
self.warning_color = "\033[0;33m%s\033[0m"
self.error_color = "\033[0;31m%s\033[0m"
self.path_color = "\033[0;20m%s\033[0m"
self.log_level_color = self.error_color
self.formatter = self.update_logging_formatter()
self.console_output_level = "INFO"
self.file_output_level = "INFO"
self.get_logger() # 在初始化的时候,去创建控制台句柄和文件句柄
def update_logging_formatter(self):
return logging.Formatter(self.info_color % '%(asctime)s -' +
self.path_color % ' %(pathname)s[line:%(lineno)d] - ' +
self.log_level_color % '%(levelname)s: ' +
self.msg_color % '%(message)s')
def set_log_level(self, level):
level = level.strip().upper()
self.console_handler.setLevel(level)
self.file_handler.setLevel(level)
pass
def mod_font_color_by_level(self, level):
if level == "ERROR":
self.log_level_color = self.error_color
elif level == "WARNING":
self.log_level_color = self.warning_color
elif level == "INFO":
self.log_level_color = self.info_color
self.formatter = self.update_logging_formatter()
self.console_handler.setFormatter(self.formatter)
self.file_handler.setFormatter(self.formatter)
def error(self, *msg):
self.mod_font_color_by_level("ERROR")
super().error(msg)
pass
def warning(self, *msg):
self.mod_font_color_by_level("WARNING")
super().warning(msg)
def info(self, *msg):
self.mod_font_color_by_level("INFO")
super().info(msg)
def get_logger(self):
if not self.handlers:
self.console_handler = logging.StreamHandler()
self.console_handler.setFormatter(self.formatter)
self.console_handler.setLevel(self.console_output_level)
self.addHandler(self.console_handler)
self.file_handler = TimedRotatingFileHandler(filename=os.path.join(LOG_PATH, self.log_file_name),
when='D',
interval=1,
backupCount=self.backup_count,
delay=True,
encoding='utf-8')
self.file_handler.setFormatter(self.formatter)
self.file_handler.setLevel(self.file_output_level)
self.addHandler(self.file_handler)
#测试代码
# log = Logger()
# log.info("这里我要打印一个info日志")
# log.warning("这里我要打印一个warning日志")
# log.error("这里我要打印一个error日志")
#
# log.set_log_level("WARNING")
# log.info("修改level为warning后,打印一个info日志")
# log.warning("修改level为warning后,打印一个warning日志")
# log.error("修改level为warning后,打印一个error日志")
代码解读
首先是要去继承logging.Logger这个基类,然后初始化,并设置一些基本的配置,比如打印的日志级别,以及字体颜色.特别注意,在初始化的过程中,我们需要去创建一个控制台的句柄,以及创建一个文件的句柄,将输出的日志同时输出到这两个地方.句柄的话,就相当于C语言里面的指针相当于是可以去调用某些东西,但是在这里的感觉,就好像是如果你要打印日志的话,他就会同时调用这个句柄去打印到控制套和文件中.
我这里的操作是将两个句柄都直接加到这个Logger的类中,这样子的好处就是,实例化Logger这个类的时候,比如log=Logger后,直接log.error()就可以调用到我们说重谢的类了.我之前见过一个写的有点误解的代码,他首先是创建一个self.logger变量,然后将句柄添加到这个变量中,这样子调用self.logger.error的时候,就会找到库里面原来的函数,就没有办法调用到我们自己想要重写的类,这样子的话,就不方便去封装了.
所以的话,我的做法就是直接将句柄添加到类中比如self.addHandler(self.file_handler),如果想要看那个我爬过坑的代码,就看看我的参考博客把,在这里我还是觉我写的要好一些
def get_logger(self):
if not self.handlers:
self.console_handler = logging.StreamHandler()
self.console_handler.setFormatter(self.formatter)
self.console_handler.setLevel(self.console_output_level)
self.addHandler(self.console_handler)
self.file_handler = TimedRotatingFileHandler(filename=os.path.join(LOG_PATH, self.log_file_name),
when='D',
interval=1,
backupCount=self.backup_count,
delay=True,
encoding='utf-8')
self.file_handler.setFormatter(self.formatter)
self.file_handler.setLevel(self.file_output_level)
self.addHandler(self.file_handler)
有一个我优化的地方,那就是在我重构error,info,warning函数的时候,我想着就是要修改打印时候的颜色,所以我就把那个修改颜色并且设置formatter的代码抽出来,单独携程一个代码,这样子估计可读性会好很多.
好啦,写好了,然后再这个文件中也有对应的测试代码.
如何使用
另外我们来看看在脚本中如何使用吧.我首先是在测试用例的基类中去实例化这个打印日志的类,然后由测试用例脚本去继承,然后再去调用来打印
import os
import unittest
from utils.config import Config
from utils.log import Logger
class BaseCase(unittest.TestCase):
URL = Config().get('URL')
base_path = os.path.dirname(os.path.abspath(__file__)) + '\..'
driver_path = "E:\代码空间\auto_test_framework\drivers\chrromedriver.exe"
log = Logger()
pass
测试脚本的代码
from baseCase.base_case import BaseCase
class TestBaiDu(BaseCase):
locator_kw = (By.ID, 'kw')
locator_su = (By.ID, 'su')
locator_result = (By.XPATH, '//div[contains(@class, "result")]/h3/a')
def setUp(self):
self.log.error("测试输出日志")
self.driver = webdriver.Chrome(executable_path=self.driver_path)
self.driver.get(self.URL)
总结一下,写完代码之后,看起来就很简单,不过在这之前,看别人的代码却看得有点糊涂糊涂的.加油啦