在Python测试开发中,pytest是最常用的测试框架之一,而logging模块是Python内置的标准日志工具。将两者结合可以实现测试过程的实时跟踪,让测试执行状态、关键参数、异常信息清晰可见,大幅提升问题排查效率。
logging模块基础配置
在使用logging之前,需要先了解基础配置方式,确保日志能按照预期格式和级别输出。logging的核心配置包括日志级别、输出格式、输出目标三个部分。
基础配置示例
以下是一个简单的logging配置示例,设置日志级别为INFO,输出格式包含时间、日志级别和具体内容:
import logging
# 基础配置
logging.basicConfig(
level=logging.INFO, # 设置日志级别为INFO,低于该级别的日志不会输出
format='%(asctime)s - %(levelname)s - %(message)s', # 日志输出格式
datefmt='%Y-%m-%d %H:%M:%S' # 时间格式
)
# 测试日志输出
logging.debug("这是debug级别的日志,不会输出")
logging.info("这是info级别的日志,会输出")
logging.warning("这是warning级别的日志,会输出")
pytest中集成logging的方法
pytest本身没有内置的logging集成机制,但可以通过两种方式实现:一种是在测试用例中直接配置logging,另一种是通过pytest的fixture实现全局日志配置。
方式一:测试用例内单独配置
在单个测试用例中配置logging,适合临时调试或者特定用例的日志需求:
import logging
import pytest
def test_demo():
# 用例内配置logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logging.info("开始执行test_demo用例")
a = 10
b = 20
logging.info(f"计算a加b的结果,a={a}, b={b}")
assert a + b == 30
logging.info("test_demo用例执行完成")
方式二:通过fixture实现全局配置
使用pytest的fixture可以实现所有测试用例共享的logging配置,避免重复代码:
import logging
import pytest
@pytest.fixture(scope="session", autouse=True)
def setup_logging():
# 会话级别的fixture,自动执行,所有用例共享配置
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
force=True # Python3.8+支持,强制重新配置logging,避免其他配置干扰
)
yield
def test_add():
logging.info("开始执行test_add用例")
result = 1 + 2
logging.info(f"计算结果:{result}")
assert result == 3
def test_subtract():
logging.info("开始执行test_subtract用例")
result = 5 - 3
logging.info(f"计算结果:{result}")
assert result == 2
不同测试场景的日志输出策略
根据测试场景的不同,可以调整logging的配置和输出内容,让日志更有针对性。
正常流程跟踪
在正常测试流程中,日志可以记录用例开始、关键参数、中间结果、用例结束等信息:
import logging
import pytest
def test_user_login():
logging.info("开始执行用户登录测试用例")
username = "test_user"
password = "test_pass_123"
logging.info(f"登录参数:用户名={username}, 密码={password}")
# 模拟登录逻辑
login_result = True
logging.info(f"登录结果:{login_result}")
assert login_result is True
logging.info("用户登录测试用例执行完成")
异常场景跟踪
在测试异常场景时,可以结合try-except捕获异常并输出详细日志:
import logging
import pytest
def test_divide_exception():
logging.info("开始执行除法异常测试用例")
a = 10
b = 0
logging.info(f"除法参数:被除数={a}, 除数={b}")
try:
result = a / b
logging.info(f"除法结果:{result}")
except ZeroDivisionError as e:
logging.error(f"捕获到除零异常:{e}", exc_info=True) # exc_info=True会输出异常堆栈信息
assert str(e) == "division by zero"
logging.info("除法异常测试用例执行完成")
日志级别与输出控制
logging提供了多个日志级别,可以根据测试阶段调整级别,开发阶段用DEBUG级别查看详细信息,正式执行阶段用INFO或WARNING级别减少冗余输出。
| 日志级别 | 数值 | 适用场景 |
|---|---|---|
| DEBUG | 10 | 开发调试阶段,输出详细的中间变量、执行步骤 |
| INFO | 20 | 正常测试执行,输出关键流程和结果 |
| WARNING | 30 | 测试中出现非预期但不影响执行的情况 |
| ERROR | 40 | 测试执行出现错误,用例可能失败 |
| CRITICAL | 50 | 严重错误,测试无法继续执行 |
可以通过修改logging的level参数调整输出级别,例如设置为logging.DEBUG可以输出所有级别的日志,设置为logging.WARNING则只输出WARNING及以上级别的日志。
注意事项
- 避免在测试中使用print输出调试信息,print无法控制级别,也无法记录时间等额外信息,logging是更规范的选择。
- 如果测试中使用了第三方库的logging配置,可能需要使用
force=True参数(Python3.8+)强制覆盖配置,避免日志输出不符合预期。 - 不要在日志中输出敏感信息,比如用户密码、接口密钥等,避免信息泄露。
- 对于复杂的测试项目,可以将logging配置单独放在一个配置文件中,方便统一管理和修改。