如何将 pytest 配置为 raise/trigger BytesWarning?
How to configure pytest to raise/trigger BytesWarning?
也许我做错了,因为我的搜索没有找到任何有用的东西。
在调用 python 解释器时添加 -b
(-bb
) option 将在隐式字节到字符串或字节到 int 转换发生时发出警告(引发):
Issue a warning when comparing bytes or bytearray with str or bytes with int. Issue an error when the option is given twice (-bb).
我想用 pytest 围绕这个编写一个单元测试。即,我想做
# foo.py
import pytest
def test_foo():
with pytest.raises(BytesWarning):
print(b"This is a bytes string.")
当调用上面的 pytest foo.py
时,测试将失败(没有 BytesWarning
引发)。当我将上述测试称为 python -bb -m pytest foo.py
时,它将通过,因为 BytesWarning 作为异常引发。到目前为止一切顺利。
我无法解决的问题(我似乎也无法在互联网上找到任何有用的东西)是 if/how 可以将 pytest 配置为自动执行此操作,以便我可以 运行 pytest --some_arg foo.py
它会做预期的事情。这可能吗?
当您执行 pytest foo.py
时,您的 shell 将查找 pytest
程序。你可以通过命令which pytest
知道将执行哪一个。对我来说,/home/stack_overflow/venv/bin/pytest
看起来像这样:
#!/home/stack_overflow/venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pytest import console_main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(console_main())
它只是从 pytest
库中调用 console_main()
。
加个print(sys.argv)
就可以看到是怎么调用的了。对我来说,是 ['/home/stack_overflow/venv/bin/pytest', 'so70782647.py']
。它匹配从第一行开始的路径,称为 shebang。它指示应如何调用您的程序。在这里,它使用我的 venv 中的 python
指示 运行 文件。
如果我修改行:
#!/home/stack_overflow/venv/bin/python -bb
# ^^^^
现在你的测试通过了。
这可能是一个解决方案,虽然不是很优雅。
您可能会注意到,即使是现在,打印 sys.argv
时也不会出现 -bb
。原因在the doc you linked yourself中解释:
An interface option terminates the list of options consumed by the interpreter, all consecutive arguments will end up in sys.argv [...]
因此无法使用 sys.argv
.
检查它是否被激活
我发现了一个关于如何从解释器的内部状态中检索它们的问题,以防您有兴趣将其作为测试的先决条件进行检查:. Although, checking for sys.flags.bytes_warning
在我们的例子中更简单 ({0: None, 1: '-b', 2: '-bb'}
).
继续你的问题,如何使用 -bb
解释器选项 运行 pytest?
您已经有了解决方案:python -bb -m pytest foo.py
.
如果您愿意,可以创建一个文件 pytest
,其内容只是 python -bb -m pytest $@
(不要忘记使其可执行)。 运行 它与 ./pytest foo.py
。或者将其设为 alias.
你不能告诉 pytest 你想要哪个 Python 解释器选项,因为 pytest 已经 运行ning 在解释器本身中,它已经处理了它自己的选项。
据我所知,这些选项确实不容易改变。我想如果您可以写入 PyConfig
C 结构,它就会产生预期的效果。例如,请参阅 function bytes_richcompare
执行 :
if (_Py_GetConfig()->bytes_warning && (op == Py_EQ || op == Py_NE)) {
if (PyUnicode_Check(a) || PyUnicode_Check(b)) {
if (PyErr_WarnEx(PyExc_BytesWarning,
"Comparison between bytes and string", 1))
return NULL;
}
然后您可以在测试中激活它,如:
def test_foo():
if sys.flags.bytes_warning < 2:
# change PyConfig.bytes_warning
assert sys.flags.bytes_warning == 2
with pytest.raises(BytesWarning):
print(b"This is a bytes string.")
# change back the PyConfig.bytes_warning
但我认为如何做到这一点应该是另一个问题。
作为解决方法,您可以像这样使用 pytest.warns
:
def test_foo():
with pytest.warns(BytesWarning):
print(b"This is a bytes string.")
它只需要 -b
选项(尽管 -bb
也可以)。
也许我做错了,因为我的搜索没有找到任何有用的东西。
在调用 python 解释器时添加 -b
(-bb
) option 将在隐式字节到字符串或字节到 int 转换发生时发出警告(引发):
Issue a warning when comparing bytes or bytearray with str or bytes with int. Issue an error when the option is given twice (-bb).
我想用 pytest 围绕这个编写一个单元测试。即,我想做
# foo.py
import pytest
def test_foo():
with pytest.raises(BytesWarning):
print(b"This is a bytes string.")
当调用上面的 pytest foo.py
时,测试将失败(没有 BytesWarning
引发)。当我将上述测试称为 python -bb -m pytest foo.py
时,它将通过,因为 BytesWarning 作为异常引发。到目前为止一切顺利。
我无法解决的问题(我似乎也无法在互联网上找到任何有用的东西)是 if/how 可以将 pytest 配置为自动执行此操作,以便我可以 运行 pytest --some_arg foo.py
它会做预期的事情。这可能吗?
当您执行 pytest foo.py
时,您的 shell 将查找 pytest
程序。你可以通过命令which pytest
知道将执行哪一个。对我来说,/home/stack_overflow/venv/bin/pytest
看起来像这样:
#!/home/stack_overflow/venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pytest import console_main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(console_main())
它只是从 pytest
库中调用 console_main()
。
加个print(sys.argv)
就可以看到是怎么调用的了。对我来说,是 ['/home/stack_overflow/venv/bin/pytest', 'so70782647.py']
。它匹配从第一行开始的路径,称为 shebang。它指示应如何调用您的程序。在这里,它使用我的 venv 中的 python
指示 运行 文件。
如果我修改行:
#!/home/stack_overflow/venv/bin/python -bb
# ^^^^
现在你的测试通过了。
这可能是一个解决方案,虽然不是很优雅。
您可能会注意到,即使是现在,打印 sys.argv
时也不会出现 -bb
。原因在the doc you linked yourself中解释:
An interface option terminates the list of options consumed by the interpreter, all consecutive arguments will end up in sys.argv [...]
因此无法使用 sys.argv
.
检查它是否被激活
我发现了一个关于如何从解释器的内部状态中检索它们的问题,以防您有兴趣将其作为测试的先决条件进行检查:sys.flags.bytes_warning
在我们的例子中更简单 ({0: None, 1: '-b', 2: '-bb'}
).
继续你的问题,如何使用 -bb
解释器选项 运行 pytest?
您已经有了解决方案:python -bb -m pytest foo.py
.
如果您愿意,可以创建一个文件 pytest
,其内容只是 python -bb -m pytest $@
(不要忘记使其可执行)。 运行 它与 ./pytest foo.py
。或者将其设为 alias.
你不能告诉 pytest 你想要哪个 Python 解释器选项,因为 pytest 已经 运行ning 在解释器本身中,它已经处理了它自己的选项。
据我所知,这些选项确实不容易改变。我想如果您可以写入 PyConfig
C 结构,它就会产生预期的效果。例如,请参阅 function bytes_richcompare
执行 :
if (_Py_GetConfig()->bytes_warning && (op == Py_EQ || op == Py_NE)) {
if (PyUnicode_Check(a) || PyUnicode_Check(b)) {
if (PyErr_WarnEx(PyExc_BytesWarning,
"Comparison between bytes and string", 1))
return NULL;
}
然后您可以在测试中激活它,如:
def test_foo():
if sys.flags.bytes_warning < 2:
# change PyConfig.bytes_warning
assert sys.flags.bytes_warning == 2
with pytest.raises(BytesWarning):
print(b"This is a bytes string.")
# change back the PyConfig.bytes_warning
但我认为如何做到这一点应该是另一个问题。
作为解决方法,您可以像这样使用 pytest.warns
:
def test_foo():
with pytest.warns(BytesWarning):
print(b"This is a bytes string.")
它只需要 -b
选项(尽管 -bb
也可以)。