我们在一个单独的python文件中定义了所有自定义断言,这个文件不是测试模块。
例如:
custom_asserts.py
class CustomAsserts(object):
def silly_assert(self, foo, bar):
assert foo == bar , 'some error message'
如果我们在测试中直接使用assert
,我们将获得有关AssertionError的额外信息,这非常有用。
在测试中直接使用断言的输出:
> assert 'foo' == 'bar', 'some error message'
E AssertionError: some error message
E assert 'foo' == 'bar'
E - foo
E + bar
但我们发现如果我们调用我们在单独模块中定义的断言方法,则不会显示额外信息。
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 docs Advanced assertion introspection
中找到了这个pytest仅重写由其测试直接发现的测试模块 收集过程,因此断言支持模块不是 自己测试模块不会被重写。
所以我的问题是,有没有办法让pytest像测试模块那样对其他模块执行相同的断言重写?或者有没有任何黑客的方法来实现这一目标?
答案 0 :(得分:8)
更新
Pytest 3.0引入了一种新方法register_assert_rewrite
来实现这个确切的功能。如果您使用pytest 3.0或更高版本,请尝试此操作。 register_assert_rewrite
原始答案:
这有点回答我自己的问题,但我认为我找到了解决方案并希望分享。
诀窍在于pytest如何收集测试模块。我们可以在python_files
中定义pytest.ini
,以便pytest将更多模块视为测试模块。
例如,在我的例子中,我的所有自定义断言模块都以“断言”结束,因此我的pytest.ini
是:
[pytest]
python_files = *asserts.py test_*.py *_test.py
另一个棘手的问题是conftest.py
。看来我们必须避免在conftest.py
中导入断言模块。我的假设是看起来技术pytest用来重写assert实际上是重写.pyc
文件,并且因为conftest.py
在收集之前加载,如果我们导入断言模块,.pyc
的将在收集之前生成模块,这可能使pytest无法再次重写.pyc
文件。
所以在我的conftest.py中,我必须做的事情是:
@pytest.fixture(autouse=Ture)
def setup_asserts(request):
from custom_asserts import CustomAsserts
request.instance.asserts = CustomAsserts()
我将获得额外的错误信息,就像在测试脚本中直接使用关键字assert
一样。