[py-dev] controlling assertions and difflib

Floris Bruynooghe flub at devork.be
Wed Sep 29 01:12:53 CEST 2010


Hi

As Holger pointed out the following test hangs py.test in my assertion
clone, it triggers a bug in difflib:

def test_hang_in_diff():
    x = "1\n" * 1000 + "abc" + "2\n" * 1000
    y = "1\n" * 1000 + "def" + "2\n" * 1000
    assert x == y

It seems difflib can not deal with the 1000 identical trailing items.
It fails with a TypeError somewhere very deep in a recursion or, when
consuming the generator inside a list comprehension, just completely
hangs.  Also before failing it considers all the 2s as different too.
Rather then debugging difflib (there are several possible bugs on
bugs.python.org which might relate to this) I've come up with some
code that does produce this instead:

______________________________ test_hang_in_diff _______________________________
/tmp/sandbox/test_bugs.py:4: in test_hang_in_diff
>       assert x == y
E       assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n...n2\n2\n2\n2\n'
E         Skipping 1990 identical leading characters in diff
E         Skipping 1991 identical trailing characters in diff
E           1
E           1
E           1
E           1
E           1
E         - abc2
E         + def2
E           2
E           2
E           2
E           2

Another solution is to use context_diff() which does not have this
problem, but for some reason also considers all the trailing 2s to be
different.  Additionally context diff also doesn't provide the nice
markers for differences inside a line which might be problematic as
there's no guarantee there will be nice line endings in the input.

In general I was already thinking of cutting off similar prefixes and
suffixes before using ndiff, so this doesn't seem that bad to me.  Do
others think this is acceptable?

This whole issue made me wonder if it should be possible to disable
the pytest_assert_binrepr hook.  It is probably sufficient to add an
option which can be checked right at the start of the builtin
pytest_assert_binrepr hook which will just return None or [] right
away.  But what is the best way to access the config setting from
there?  Is it fine to use py.test.config or should the setting be
piggy-backed on some global again (e.g. change the current
py.builtin.builtins.AssertionError._pytesthook into a ._pytestconfig)?
 Or maybe there's a more elegant solution for this that I'm unaware
of?

Regards
Floris

-- 
Debian GNU/Linux -- The Power of Freedom
www.debian.org | www.gnu.org | www.kernel.org



More information about the Pytest-dev mailing list