如何配置pytest自动触发/抛出BytesWarning异常?
-bb 严格bytes检测方案 背景
调用Python解释器时添加-b(-bb)选项,可在发生隐式bytes与str比较、bytes与int比较操作时触发警告(-bb为直接抛出异常),官方规则说明:
当bytes或bytearray与str比较、bytes与int比较时触发警告;重复传入
-b即使用-bb参数时直接抛出错误。
编写对应pytest单元测试时,直接执行pytest foo.py会因为解释器未开启bytes检测逻辑导致测试失败,只有执行python -bb -m pytest foo.py时测试才能正常通过。
注:原示例代码中print(b"This is a bytes string.")不会触发BytesWarning,实际测试需要使用b"a" == "a"这类会触发跨类型比较的逻辑,修正后的测试代码如下:
# foo.py import pytest def test_foo(): with pytest.raises(BytesWarning): b"test_bytes" == "test_str"
实现方式
方式1:自定义pytest参数自动加载-bb模式(推荐,跨平台无依赖)
在项目根目录新建conftest.py文件,写入以下代码:
import sys import os from pytest import Parser def pytest_addoption(parser: Parser): parser.addoption( "--strict-bytes", action="store_true", default=False, help="启用Python -bb模式,严格检测bytes隐式比较/转换问题" ) def pytest_configure(config): # 检测到传入--strict-bytes参数且当前未开-bb模式时,自动重启带-bb参数的解释器 if config.getoption("--strict-bytes") and sys.flags.bytes_warning < 2: os.execv( sys.executable, [sys.executable, "-bb", "-m", "pytest", *sys.argv[1:]] )
配置完成后,直接执行pytest --strict-bytes foo.py即可自动启用-bb检测逻辑,不需要手动输入python -bb -m pytest。
如果需要默认全局开启-bb模式,不需要手动传--strict-bytes,直接把pytest_configure里的config.getoption("--strict-bytes")判断条件去掉即可,之后在该项目下执行任意pytest命令都会自动加载-bb模式。
该逻辑不会出现死循环:重启后的解释器已经带了-bb参数,sys.flags.bytes_warning值为2,不会触发二次重启。
方式2:命令行警告参数(仅模拟警告转错误,不触发检测逻辑,不推荐)
网上常见的pytest -W error::BytesWarning foo.py写法,仅能将已触发的BytesWarning转为异常,无法打开Python解释器内置的bytes比较检测开关,不带-b参数时解释器根本不会生成BytesWarning,因此该方式无法达到-bb的实际效果。
内容的提问来源于stack exchange,提问作者FirefoxMetzger

