We defined all our custom assertions in a separate python file which is not a test module.
For example:
custom_asserts.py
class CustomAsserts(object):
def silly_assert(self, foo, bar):
assert foo == bar , 'some error message'
If we use assert
directly in tests, we will get extra info about the AssertionError, which is very useful.
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')
Output after running the test:
> assert 'foo' == 'bar', 'some error message'
E AssertionError: some error message
And we also found this in pytest docs: Advanced assertion introspection
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.
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?
Update:
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
Original answer:
It's kind of wired to answer my own question but I think I found the solution and want to share.
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.
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
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.
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()
And I will get the extra error info just like using keyword assert
directly in test script.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With