From e2201fe3a995a570a86b526e3acc1e431bea4c1e Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Sun, 16 Oct 2011 11:51:15 +0100 Subject: [PATCH] Look up the pytest_assertrepr_compare hook for each test item Before this was only done at the time the assertion plugin was loaded. This lead to counter-intuitive behaviour where two subdirectories with a pytest_assertrepr_compare hook in their conftest.py would not work, only one would ever be used. This defers assiging the _pytest.assertion.util._reprcompare function until the item is loaded (pytest_runtest_setup) so that it can use the hookrelay of the test item to find the appropriate pytest_assertrepr_compare hook for the item. This fixes issue #77. --- _pytest/assertion/__init__.py | 31 ++++++++++++++++++------------- testing/test_assertion.py | 31 ++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py index a999b7c15..bac5f653d 100644 --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -43,23 +43,10 @@ def pytest_configure(config): mode = "reinterp" if mode != "plain": _load_modules(mode) - def callbinrepr(op, left, right): - hook_result = config.hook.pytest_assertrepr_compare( - config=config, op=op, left=left, right=right) - for new_expl in hook_result: - if new_expl: - res = '\n~'.join(new_expl) - if mode == "rewrite": - # The result will be fed back a python % formatting - # operation, which will fail if there are extraneous - # '%'s in the string. Escape them here. - res = res.replace("%", "%%") - return res m = monkeypatch() config._cleanup.append(m.undo) m.setattr(py.builtin.builtins, 'AssertionError', reinterpret.AssertionError) - m.setattr(util, '_reprcompare', callbinrepr) hook = None if mode == "rewrite": hook = rewrite.AssertionRewritingHook() @@ -82,6 +69,24 @@ def pytest_collection(session): if hook is not None: hook.set_session(session) +def pytest_runtest_setup(item): + def callbinrepr(op, left, right): + hook_result = item.ihook.pytest_assertrepr_compare( + config=item.config, op=op, left=left, right=right) + for new_expl in hook_result: + if new_expl: + res = '\n~'.join(new_expl) + if item.config.getvalue("assertmode") == "rewrite": + # The result will be fed back a python % formatting + # operation, which will fail if there are extraneous + # '%'s in the string. Escape them here. + res = res.replace("%", "%%") + return res + util._reprcompare = callbinrepr + +def pytest_runtest_teardown(item): + util._reprcompare = None + def pytest_sessionfinish(session): hook = session.config._assertstate.hook if hook is not None: diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 28d63e881..75b06943a 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -40,15 +40,6 @@ class TestBinReprIntegration: assert hook.left == [0, 1] assert hook.right == [0, 2] - def test_configure_unconfigure(self, testdir, hook): - assert hook == util._reprcompare - config = testdir.parseconfig() - plugin.pytest_configure(config) - assert hook != util._reprcompare - from _pytest.config import pytest_unconfigure - pytest_unconfigure(config) - assert hook == util._reprcompare - def callequal(left, right): return plugin.pytest_assertrepr_compare('==', left, right) @@ -167,6 +158,28 @@ def test_sequence_comparison_uses_repr(testdir): "*E*'y'*", ]) +@needsnewassert +def test_assertrepr_loaded_per_dir(testdir): + testdir.makepyfile(test_base=['def test_base(): assert 1 == 2']) + a = testdir.mkdir('a') + a_test = a.join('test_a.py') + a_test.write('def test_a(): assert 1 == 2') + a_conftest = a.join('conftest.py') + a_conftest.write('def pytest_assertrepr_compare(): return ["summary a"]') + b = testdir.mkdir('b') + b_test = b.join('test_b.py') + b_test.write('def test_b(): assert 1 == 2') + b_conftest = b.join('conftest.py') + b_conftest.write('def pytest_assertrepr_compare(): return ["summary b"]') + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + '*def test_base():*', + '*E*assert 1 == 2*', + '*def test_a():*', + '*E*assert summary a*', + '*def test_b():*', + '*E*assert summary b*']) + def test_assertion_options(testdir): testdir.makepyfile("""