如何让pytest在非测试模块中重写assert

时间:2016-06-30 22:44:33

标签: python pytest

我们在一个单独的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像测试模块那样对其他模块执行相同的断言重写?或者有没有任何黑客的方法来实现这一目标?

1 个答案:

答案 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一样。

相关问题