四大核心组件:构建专业日志系统
期末考试重点:Python logging模块的四大核心组件(Logger、Handler、Formatter、Filter)是自动化测试框架的重要基础,必须深度理解它们的作用机制和协作关系。
四大组件架构图
组件协作流程
- Logger:接收日志请求,判断级别是否满足条件
- Filter:对日志记录进行条件过滤(可选)
- Handler:决定日志的输出目标(控制台、文件等)
- Formatter:格式化日志消息的显示样式
1. Logger(记录器)- 日志系统的核心入口
核心职责
- 接口提供者:为应用程序提供日志记录的直接接口
- 级别控制者:决定哪些级别的日志会被处理
- 层次管理者:支持父子继承关系的层次化管理
- Handler协调者:管理和协调多个处理器
基础应用
Python
import logging
# 创建记录器
logger = logging.getLogger('automation_test')
logger.setLevel(logging.DEBUG)
# 记录不同级别的日志
logger.debug("详细调试信息")
logger.info("关键流程信息")
logger.warning("潜在问题警告")
logger.error("执行错误信息")
logger.critical("系统严重错误")
层次化管理(考试重点)
Python
# 父记录器
parent_logger = logging.getLogger('test_framework')
parent_logger.setLevel(logging.INFO)
# 子记录器(自动继承父记录器的配置)
selenium_logger = logging.getLogger('test_framework.selenium')
api_logger = logging.getLogger('test_framework.api')
database_logger = logging.getLogger('test_framework.database')
# 层次关系:test_framework ← test_framework.selenium ← test_framework.api
记录器管理最佳实践
Python
class LoggerFactory:
"""记录器工厂类 - 统一管理日志记录器"""
_loggers = {}
@classmethod
def get_logger(cls, name, level=logging.INFO):
"""获取或创建记录器"""
if name not in cls._loggers:
logger = logging.getLogger(name)
logger.setLevel(level)
cls._loggers[name] = logger
return cls._loggers[name]
@classmethod
def get_test_logger(cls, test_module):
"""获取测试模块专用记录器"""
return cls.get_logger(f'test.{test_module}')
# 使用示例
login_logger = LoggerFactory.get_test_logger('login')
search_logger = LoggerFactory.get_test_logger('search')
2. Handler(处理器)- 输出目标的决策者
核心职责
- 输出路由:决定日志记录的输出目标和方式
- 级别过滤:每个处理器可独立设置日志级别
- 格式应用:应用格式器对日志进行格式化
- 并发支持:支持多个处理器同时工作
常用处理器类型
StreamHandler - 控制台输出
Python
import logging
import sys
# 标准输出处理器
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
# 错误输出处理器
error_handler = logging.StreamHandler(sys.stderr)
error_handler.setLevel(logging.ERROR)
logger = logging.getLogger('test')
logger.addHandler(console_handler)
logger.addHandler(error_handler)
FileHandler - 基础文件输出
Python
import logging
# 基础文件处理器
file_handler = logging.FileHandler('test.log', encoding='utf-8')
file_handler.setLevel(logging.DEBUG)
# 追加模式文件处理器
append_handler = logging.FileHandler('test.log', mode='a', encoding='utf-8')
logger = logging.getLogger('test')
logger.addHandler(file_handler)
RotatingFileHandler - 大小轮转
Python
from logging.handlers import RotatingFileHandler
# 按文件大小轮转
rotating_handler = RotatingFileHandler(
'test.log', # 文件名
maxBytes=1024*1024*5, # 最大5MB
backupCount=3, # 保留3个备份
encoding='utf-8'
)
rotating_handler.setLevel(logging.DEBUG)
# 文件轮转效果:test.log → test.log.1 → test.log.2 → test.log.3
TimedRotatingFileHandler - 时间轮转
Python
from logging.handlers import TimedRotatingFileHandler
# 按时间轮转
timed_handler = TimedRotatingFileHandler(
'test.log',
when='D', # 轮转周期:H(小时)、D(天)、W(周)、M(月)
interval=1, # 每1天轮转
backupCount=7, # 保留7天的历史日志
encoding='utf-8'
)
timed_handler.setLevel(logging.DEBUG)
多处理器协作策略
Python
def setup_multi_handler_system():
"""配置多处理器协作系统"""
logger = logging.getLogger('automation')
logger.setLevel(logging.DEBUG)
logger.handlers.clear()
# 1. 控制台处理器 - 显示重要信息
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 2. 调试文件处理器 - 记录所有详细信息
debug_handler = RotatingFileHandler(
'debug.log', maxBytes=10*1024*1024, backupCount=5, encoding='utf-8'
)
debug_handler.setLevel(logging.DEBUG)
# 3. 错误文件处理器 - 专门记录错误
error_handler = RotatingFileHandler(
'error.log', maxBytes=5*1024*1024, backupCount=3, encoding='utf-8'
)
error_handler.setLevel(logging.ERROR)
# 4. 添加所有处理器
logger.addHandler(console_handler)
logger.addHandler(debug_handler)
logger.addHandler(error_handler)
return logger
3. Formatter(格式器)- 输出样式的美化师
核心职责
- 信息组织:决定日志消息的显示格式和内容布局
- 时间格式化:控制时间戳的显示样式
- 字段选择:选择要显示的日志字段信息
- 可读性优化:提高日志的可读性和专业性
格式化字段说明(考试重点)
| 字段名 | 含义 | 示例 |
|---|---|---|
| %(asctime)s | 时间戳 | 2024-01-15 14:30:25 |
| %(levelname)s | 日志级别 | INFO、ERROR |
| %(name)s | 记录器名称 | test.login |
| %(filename)s | 文件名 | test_login.py |
| %(lineno)d | 行号 | 25 |
| %(funcName)s | 函数名 | test_valid_login |
| %(message)s | 日志消息 | 登录测试执行成功 |
| %(pathname)s | 文件完整路径 | /tests/test_login.py |
| %(module)s | 模块名 | test_login |
实用格式器配置
Python
import logging
# 1. 简洁格式器 - 适合控制台
simple_formatter = logging.Formatter(
'%(levelname)s - %(message)s'
)
# 2. 标准格式器 - 适合一般文件记录
standard_formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 3. 详细格式器 - 适合调试文件
detailed_formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(funcName)s() - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 4. 错误格式器 - 包含异常信息
error_formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s\n%(exc_info)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
自定义格式器
Python
class CustomFormatter(logging.Formatter):
"""自定义格式器 - 添加特殊功能"""
def format(self, record):
# 添加自定义字段
record.test_case = getattr(record, 'test_case', 'unknown')
record.test_step = getattr(record, 'test_step', 'N/A')
# 根据级别调整格式
if record.levelno >= logging.ERROR:
# 错误级别添加更多上下文信息
self._style._fmt = '%(asctime)s - [%(test_case)s] - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
else:
# 普通级别使用简洁格式
self._style._fmt = '%(asctime)s - %(levelname)s - %(message)s'
return super().format(record)
# 使用自定义格式器
custom_formatter = CustomFormatter()
handler = logging.StreamHandler()
handler.setFormatter(custom_formatter)
4. Filter(过滤器)- 精准控制的守门员
核心职责
- 条件过滤:基于自定义条件过滤日志记录
- 动态控制:运行时动态调整过滤策略
- 精细管理:比日志级别更精细的控制机制
- 特殊场景:处理复杂的日志过滤需求
基础过滤器应用
Python
import logging
class TestCaseFilter(logging.Filter):
"""测试用例过滤器 - 只允许特定测试用例的日志"""
def __init__(self, allowed_test_cases):
super().__init__()
self.allowed_test_cases = allowed_test_cases
def filter(self, record):
# 只允许指定测试用例的日志通过
test_case = getattr(record, 'test_case', None)
return test_case in self.allowed_test_cases
# 使用过滤器
test_filter = TestCaseFilter(['login_test', 'search_test'])
handler = logging.StreamHandler()
handler.addFilter(test_filter)
# 记录日志时添加测试用例信息
logger = logging.getLogger('test')
logger.addHandler(handler)
# 创建日志记录时添加额外信息
record = logging.LogRecord(
name='test', level=logging.INFO, pathname='', lineno=0,
msg='测试执行成功', args=(), exc_info=None
)
record.test_case = 'login_test' # 添加自定义字段
logger.handle(record)
高级过滤器示例
Python
class PerformanceFilter(logging.Filter):
"""性能过滤器 - 过滤执行时间相关的日志"""
def filter(self, record):
# 只允许包含性能关键词的日志
performance_keywords = ['timeout', 'slow', 'performance', 'duration']
message = record.getMessage().lower()
return any(keyword in message for keyword in performance_keywords)
class LevelRangeFilter(logging.Filter):
"""级别范围过滤器 - 只允许特定范围的日志级别"""
def __init__(self, min_level, max_level):
super().__init__()
self.min_level = min_level
self.max_level = max_level
def filter(self, record):
return self.min_level <= record.levelno <= self.max_level
# 应用示例:只记录WARNING到ERROR级别的日志
range_filter = LevelRangeFilter(logging.WARNING, logging.ERROR)
handler.addFilter(range_filter)
四大组件综合应用实例
Python
import logging
from logging.handlers import RotatingFileHandler
import sys
def setup_comprehensive_logging():
"""配置完整的四大组件协作系统"""
# 1. 创建Logger
logger = logging.getLogger('test_automation')
logger.setLevel(logging.DEBUG)
logger.handlers.clear()
# 2. 创建Formatter
console_formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s',
datefmt='%H:%M:%S'
)
file_formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(funcName)s() - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 3. 创建Handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(console_formatter)
file_handler = RotatingFileHandler(
'automation.log', maxBytes=5*1024*1024, backupCount=3, encoding='utf-8'
)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(file_formatter)
# 4. 创建Filter
class TestFilter(logging.Filter):
def filter(self, record):
# 过滤掉第三方库的DEBUG信息
if record.levelno == logging.DEBUG and not record.name.startswith('test'):
return False
return True
test_filter = TestFilter()
file_handler.addFilter(test_filter)
# 5. 组装系统
logger.addHandler(console_handler)
logger.addHandler(file_handler)
return logger
# 使用综合日志系统
logger = setup_comprehensive_logging()
logger.info("日志系统初始化完成")
logger.debug("这是调试信息")
logger.warning("这是警告信息")
logger.error("这是错误信息")
这四大组件的精密协作,构建了功能强大、灵活可控的日志系统,是自动化测试框架不可或缺的重要基础设施。