web自动化中的日志模块

在 Web 自动化框架中加入日志模块是提升调试效率和可维护性的重要手段。下面给出一个完整的日志集成方案,使用 Python 内置的 logging 模块,同时输出到控制台和文件,并自动记录每个操作的关键信息。

一、日志模块设计

1. 创建独立的日志配置模块

在项目根目录下新建 common/logger.py:

python 复制代码
import logging
import os
import time
from datetime import datetime

def setup_logger(name='AutoTest', log_level=logging.INFO, log_dir='logs'):
    """
    配置并返回 logger 实例
    :param name: logger 名称
    :param log_level: 日志级别
    :param log_dir: 日志文件存储目录
    :return: logger 对象
    """
    # 创建日志目录(如果不存在)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # 生成日志文件名(按日期分割)
    log_filename = os.path.join(log_dir, f"{datetime.now().strftime('%Y%m%d')}.log")

    # 创建 logger
    logger = logging.getLogger(name)
    logger.setLevel(log_level)

    # 避免重复添加 handler
    if logger.handlers:
        return logger

    # 文件 handler(记录所有级别)
    file_handler = logging.FileHandler(log_filename, encoding='utf-8')
    file_handler.setLevel(logging.DEBUG)

    # 控制台 handler(只记录 INFO 及以上)
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)

    # 定义日志格式
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    file_handler.setFormatter(formatter)
    console_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)

    return logger

# 创建一个全局默认 logger
default_logger = setup_logger()

2. 在 BasePage 中集成日志

修改 BasePage,让每个操作自动记录日志,同时保留原有 self.logger 供子类使用:

python

python 复制代码
from wework.common.logger import setup_logger

class BasePage:
    def __init__(self, page: Page):
        self.logger = setup_logger('BasePage')   # 每个页面实例可拥有独立 logger


# ... 原有代码 ...

3. 在测试用例中使用日志

在 conftest.py 或测试文件中,可以获取 logger 并记录测试步骤:

python 复制代码
# conftest.py
from wework.common.logger import setup_logger
import pytest

@pytest.fixture(scope="session")
def test_logger():
    return setup_logger('Test')

# 测试用例
def test_example(test_logger):
    test_logger.info("开始执行测试用例: test_example")
    # ... 测试步骤
    test_logger.info("断言验证通过")

二、增强功能:记录页面操作详情

1. 装饰器自动记录方法调用

为需要记录的方法增加装饰器,自动打印方法名和参数:

python 复制代码
def log_method(func):
    def wrapper(self, *args, **kwargs):
        self.logger.info(f"调用 {func.__name__} → args={args}, kwargs={kwargs}")
        return func(self, *args, **kwargs)
    return wrapper

# 使用示例
@log_method
def click(self, ...):
    pass

2. 记录截图/页面源码(错误时)

在 BasePage 中增加错误时截图的方法:

python 复制代码
def take_screenshot(self, name=None):
    if name is None:
        name = f"screenshot_{int(time.time())}.png"
    path = os.path.join("screenshots", name)
    os.makedirs("screenshots", exist_ok=True)
    self.page.screenshot(path=path)
    self.logger.info(f"截图已保存: {path}")
    return path

在 click 或 input_text 异常捕获中调用截图:

python 复制代码
except Exception as e:
    self.take_screenshot("error_click.png")
    self.logger.error(f"点击失败: {e}")
    raise

3. 记录网络请求(可选)

如果需要记录 API 请求,可以监听 Playwright 的 Request/Response 事件:

python 复制代码
def setup_network_logging(self):
    self.page.on("request", lambda req: self.logger.debug(f"请求: {req.method} {req.url}"))
    self.page.on("response", lambda res: self.logger.debug(f"响应: {res.status} {res.url}"))

三、日志轮转与清理

为避免日志文件过大,可使用 RotatingFileHandler 或按天切割(已实现按天)。如需保留最近 N 天:

python 复制代码
import glob
def clean_old_logs(log_dir='logs', days=7):
    now = time.time()
    for f in glob.glob(os.path.join(log_dir, "*.log")):
        if os.path.getmtime(f) < now - days * 86400:
            os.remove(f)
            print(f"删除旧日志: {f}")

四、集成 pytest 的日志系统

pytest 本身有内置的日志捕获功能,可以在 pytest.ini 中配置:

python 复制代码
[pytest]
log_cli = true
log_cli_level = INFO
log_file = logs/pytest.log
log_file_level = DEBUG

这样 pytest 会自动捕获所有 print 和 logging 输出。你无需额外配置,只需在测试代码中使用 logging.getLogger() 即可与 pytest 日志集成。

相关推荐
IT_陈寒18 分钟前
SpringBoot启动慢得像蜗牛?原来是这个配置在捣鬼
前端·人工智能·后端
计算机魔术师19 分钟前
Muse Spark跑赢Gemini,但真正的底牌是这种设计
前端
PYB332 分钟前
【Web·JS·基础】函数的使用和展运算符...objs
前端·javascript
ZealSinger35 分钟前
Spring7 RestTemplate弃用迁移
java·spring·后端开发·restclient
代码方舟36 分钟前
零信任架构实战:基于天远学历信息高级版构建自动化智库入驻审查网关
运维·人工智能·架构·自动化
指针向南42 分钟前
Chrome读不了HEIC怎么办:原生解码和WASM两条路
前端·图像处理·人工智能·chrome·计算机视觉·wasm
朝朝辞暮i1 小时前
C++ 第 13 课:值传递 —— 为什么函数里改了,外面却没变?
java·c++·算法
弹简特1 小时前
【Java项目-企悦抽】16-抽奖模块01-获取活动完整信息接口实现
java·开发语言·状态模式·springboot
默_笙1 小时前
🚥 给 RAG 装一台心电监护仪:LangSmith 全链路观测(上)
前端·javascript
泡茶喝茶写代码2 小时前
A股量化数据工程:从 REST 接口到策略信号(第 1 篇):指数列表与实时行情接入
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据接口