如何让 pytest 在非测试模块中重写断言 [英] How to let pytest rewrite assert in non-test modules
问题描述
我们在一个单独的 python 文件中定义了所有自定义断言,该文件不是一个测试模块.
We defined all our custom assertions in a separate python file which is not a test module.
例如:custom_asserts.py
class CustomAsserts(object):
def silly_assert(self, foo, bar):
assert foo == bar , 'some error message'
如果我们在测试中直接使用assert
,我们会得到关于AssertionError的额外信息,这非常有用.
If we use assert
directly in tests, we will get extra info about the AssertionError, which is very useful.
在测试中直接使用 assert 的输出:
Output of directly use assert in tests:
> assert 'foo' == 'bar', 'some error message'
E AssertionError: some error message
E assert 'foo' == 'bar'
E - foo
E + bar
但是我们发现,如果调用我们在单独模块中定义的断言方法,则不会显示额外信息.
But we found that if we call the assertion method we defined in separate module, extra info won't show.
from custom_asserts import CustomAsserts
asserts = CustomAsserts()
def test_silly():
asserts.silly_assert('foo', 'bar')
运行测试后的输出:
> assert 'foo' == 'bar', 'some error message'
E AssertionError: some error message
我们也在 pytest 文档中发现了这一点:高级断言自省
And we also found this in pytest docs: Advanced assertion introspection
pytest 只重写其测试直接发现的测试模块收集过程,因此在支持的模块中断言不是自己的测试模块不会被重写.
pytest only rewrites test modules directly discovered by its test collection process, so asserts in supporting modules which are not themselves test modules will not be rewritten.
所以我的问题是,有没有办法让 pytest 像测试模块一样对其他模块进行相同的断言重写?或者有什么方法可以实现这一目标?
So my question is, is there a way to let pytest do the same assert rewriting to other modules just like test modules? Or is there any hacky way to achieve that?
推荐答案
更新:
Pytest 3.0 引入了一种新方法 register_assert_rewrite
来实现这一确切功能.如果您使用的是 pytest 3.0 或更高版本,请尝试此操作.register_assert_rewrite
Pytest 3.0 introduced a new method register_assert_rewrite
to implement this exact feature. If you are using pytest 3.0 or later, please try this. register_assert_rewrite
原答案:
回答我自己的问题有点连贯,但我想我找到了解决方案并想分享.
It's kind of wired to answer my own question but I think I found the solution and want to share.
诀窍在于 pytest 如何收集测试模块.我们可以在pytest.ini
中定义python_files
,这样pytest会考虑更多的模块作为测试模块.
The trick is in how pytest collect test modules. We can define python_files
in pytest.ini
so that pytest will consider more modules as test modules.
例如,在我的例子中,我所有的自定义断言模块都以asserts"结尾,所以我的 pytest.ini
是:
For example, in my case, all my custom asserts module ends with 'asserts', so my pytest.ini
is:
[pytest]
python_files = *asserts.py test_*.py *_test.py
另一个棘手的事情是在 conftest.py
中.看来我们必须避免在 conftest.py
中导入 asserts 模块.我的假设是看起来 pytest 用来重写断言的技术实际上是重写 .pyc
文件,并且由于 conftest.py
在收集之前加载,如果我们导入断言模块,采集前会生成模块的.pyc
,可能导致pytest无法再次重写.pyc
文件.
Another tricky thing is in conftest.py
. It seems we have to avoid import the asserts module in conftest.py
. My assumption is that it looks like the technology pytest uses to rewrite assert is actually rewrite .pyc
file, and since conftest.py
is loaded before collecting, if we import the asserts module, .pyc
of the module would be generated before collecting, which may make pytest unable to rewrite the .pyc
file again.
所以在我的 conftest.py 中,我必须做这样的事情:
So in my conftest.py, I have to do thing like:
@pytest.fixture(autouse=Ture)
def setup_asserts(request):
from custom_asserts import CustomAsserts
request.instance.asserts = CustomAsserts()
我会得到额外的错误信息,就像在测试脚本中直接使用关键字assert
一样.
And I will get the extra error info just like using keyword assert
directly in test script.
这篇关于如何让 pytest 在非测试模块中重写断言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!