With pytest, why do inherited test methods not give proper assertion output?
<p>I am working on an application that has a command line interface that I would like to test using pytest. My idea was to define test classes like</p>

<pre><code>class TestEchoCmd(Scenario):
    commands = [
        "echo foo"
    ]
    stdout = "foo\n"
</code></pre>

<p>and then use a class with a test method to do the actual test. In other words, rather than define the test method â which is always the same â in every class that describes a scenario (which would be very tedious), these classes inherit the test method from the <code>Scenario</code> class:</p>

<pre><code>class Scenario:
    commands = []
    stdout = ""

    def test_scenario(self, capsys):
        for cmd in self.commands:
            ret = my_app.execute_command(shlex.split(cmd))
            assert ret == 0
        stdout, stderr = capsys.readouterr()
        assert stdout == self.stdout
</code></pre>

<p>This works fine as long as the tests pass. If a test fails, then pytest simply outputs an <code>AssertionError</code> with no additional information, unlike in the case when the test method is not inherited and it describes the <code>assert</code>ed expression in great detail. This is counterproductive because it is impossible to tell exactly why the assertion failed.</p>

<p>Is there a way to make this work? I would really like to make the scenario descriptions as concise as possible. (I know about <code>@pytest.mark.parametrize</code> but I don't think it makes for very readable code in this case.)</p>

<p>(Oh, incidentally, this is pytest 3.0.2 as provided by Debian GNU/Linux.)</p>

<p>Found the answer myself: Pytest likes to rewrite the <code>assert</code> statements in the Python AST to add the more explicit output. This rewriting occurs (among other places) in classes that it deems to contain test methods, i.e., ones whose names start with <code>Test</code>. If a test method is inherited from a class in a different module that wouldn't otherwise be considered a test, the <code>assert</code> doesn't get rewritten, and hence no fancy error messages.</p>

<p>The solution, according to the pytest docs, is to get pytest to rewrite the <code>assert</code> statements in that other module, too, using</p>

<pre><code>pytest.register_assert_rewrite("module.name.goes.here")
</code></pre>

<p>This must be done before the module in question is imported.</p>

python inheritance py.test