[pytest-dev] Custom reporting for asserts without comparison operators?

Floris Bruynooghe flub at devork.be
Mon Mar 26 16:30:10 EDT 2018


On Fri, Mar 23 2018, Shawn Brown wrote:
> The dual behavior was an implementation detail of the hacked experiment I
> was playing with. My interest was in having something like
> pytest_assertrepr_compare() but for single-values rather than just
> comparisons.

Cool, I think the equivalent of the assertrepr hook is the FalsyValue
you have below.  But as you noticed it needs some work.

>> [0] I don't think it currently does this, so this would
>> be a feature request AFAIK.
>
> Here's an example of Pytest's current behavior using a falsey value with a
> repr:
>
>     import pytest
>
>     # Test helpers.
>     def myfunc(x):
>         if x == 42:
>             return True
>         msg = 'custom report\nmulti-line output\nmyfunc({0}) failed'
>         return FalsyValue(msg.format(x))
>
>     class FalsyValue(object):
>         def __init__(self, repr_string):
>             self.repr_string = repr_string
>
>         def __bool__(self):
>             return False
>
>         def __nonzero__(self):  # <- for py 2
>             return False
>
>         def __eq__(self, other):
>             return other == False
>
>         def __repr__(self):
>             return self.repr_string
>
>     # Test cases.
>     def test_passing():
>         assert myfunc(42)
>
>     def test_failing():
>         assert myfunc(41)
>
>
> Running this gives the following failure message:
>
>     ============================ FAILURES ============================
>     __________________________ test_failing __________________________
>
>         def test_failing():
>     >       assert myfunc(41)
>     E       assert custom report\nmulti-line output\nmyfunc(41) failed
>     E        +  where custom report\nmulti-line output\nmyfunc(41) fai
>     led = myfunc(41)
>
>     test_falsey_object.py:31: AssertionError
>     =============== 1 failed, 1 passed in 0.22 seconds ===============
>
> So this does sort-of work although the repr is duplicated and newlines are
> being escaped.

I think making this show correctly is worthwhile here.  Now there are
most likely testsuites which rely on the current "sanitisation" of the
repr output, either by design or more likely by accident.  So
implementing probably has to be a little more careful, e.g. maybe
introduce something like the __tracebackhide__ method.  But then we
should probably be more modern and have some class decorator instead
of that old locals hack (we really should also provide a modern
decorator-based API for __tracebackhide__ as well if someone feels like
a simple-ish feature).


Cheers,
Floris


More information about the pytest-dev mailing list