How to let pytest rewrite assert in non-test modules
Question: 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](http://pytest.org/latest/assert.html#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?


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.

