assertThat(..., verbose=True) sometimes generates unprintable AssertionErrors
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
testtools |
Fix Released
|
Medium
|
Martin Packman |
Bug Description
The assertThat method for use with matchers creates AssertionError instances that don't stringify on Python 2.4, 2.5, and some 2.6 minor versions when used with a non-ascii unicode argument. The testtools.
Instead of the expected output, these older Pythons get:
Traceback (most recent call last):
...
self.
File "C:\Python24\
self.
AssertionError: <unprintable AssertionError object>
Related branches
- Martin Packman: Approve
- testtools committers: Pending requested
-
Diff: 309 lines (+158/-15)7 files modifiedNEWS (+10/-1)
scripts/all-pythons (+6/-3)
testtools/compat.py (+7/-2)
testtools/matchers.py (+27/-0)
testtools/testcase.py (+3/-8)
testtools/tests/test_matchers.py (+58/-0)
testtools/tests/test_testcase.py (+47/-1)
- Jonathan Lange: Approve
-
Diff: 754 lines (+439/-32) (has conflicts)6 files modifieddoc/for-test-authors.rst (+10/-2)
testtools/compat.py (+93/-5)
testtools/matchers.py (+40/-13)
testtools/tests/test_compat.py (+127/-0)
testtools/tests/test_matchers.py (+151/-9)
testtools/tests/test_testcase.py (+18/-3)
tags: | added: unicode |
summary: |
- assertThat should be careful when handling unicode + assertThat sometimes generates unprintable AssertionErrors |
Changed in testtools: | |
status: | New → Triaged |
importance: | Undecided → Medium |
Changed in testtools: | |
status: | Triaged → In Progress |
assignee: | nobody → Jonathan Lange (jml) |
Changed in testtools: | |
assignee: | Jonathan Lange (jml) → Martin [gz] (gz) |
status: | In Progress → Fix Committed |
Changed in testtools: | |
milestone: | none → next |
Changed in testtools: | |
status: | Fix Committed → Fix Released |
This test seems to reproduce:
def test_assertThat _unicode( self):
self. failureExceptio n,
self. assertThat, crazy_char, Equals(_u("a")), verbose=True)
str_exception = _exception_ to_text( e)
self.assertIsN otNone( str_exception)
crazy_char = _u("\xa7")
e = self.assertRaises(
Also, see this discussion:
<jml> mgz: around? /bugs.launchpad .net/testtools/ +bug/675323 something_ long, DoctestMatches( pattern, doctest. REPORT_ UDIFF)) that'll be much better anyway mismatch) ' and relying on AssertionError to call __str__ (and thus, describe) matchers. Mismatch object at %x attributes=%r>" % (id(self), self.__dict__)
<mgz> aha, I was considering pinging you
<mgz> I've got an idea that might help some of the assertThat issues
<mgz> how about just putting the Mismatch object in the AssertionError rather than stringifying it? avoids a bunch of __str__ vs __unicode__ issues
<mgz> also puts the formatting entirely in the hands of the Mismatch rather than printing the Matcher at all
<mgz> I don't think there are any bad side effects from having a non-string type argument to an exception
<mgz> jml: anything in particular?
<jml> mgz: oh huh
<jml> mgz: just wanted your feedback on a bug
<jml> mgz: https:/
<ubot5> Ubuntu bug 675323 in testtools "assertThat style gives overly verbose output" [Wishlist,Triaged]
<mgz> how would you feel about just printing the "Difference" portion and none of the rest?
<mgz> in cases like assertThat(
<mgz> and trivial things like assertEqual(1, 2) are clear anyway without being explicit about what the Matcher and matchee are
<jml> mgz: basically, that's my plan.
<jml> mgz: maybe adding a verbose option to assertThat to print its current output
<jml> mgz: patch up.
<jml> mgz: regarding your earlier comment, you mean doing something like 'raise AssertionError(
<mgz> I do.
<mgz> Then we can get the logic right on the Mismatch classes, and avoid the python version variations on exception instances
<jml> Hmm.
<jml> mgz: That would change the API for mismatches, not sure that would be a problem.
<mgz> In which respect?
<jml> we don't currently insist on inheriting from Mismatch
<jml> and we don't currently use mismatch.__str__
<jml> so third-party mismatches that don't inherit will break
<mgz> hm.
<jml> where 'break' means, "<testtools.
<mgz> the other option is raising an AssertionError subclass on some python versions.
<mgz> which is also a tricky api change.
<jml> well, we could _always_ raise an AssertionError subclass
<jml> that would only break people who were expecting an exact class
<jml> but would still go alright w/ 'except AssertionError' or isinstance() checks
<jml> mgz: in some ways, I wouldn't mind raising a specialized exception for assertThat anyway. I think it would be nice to attach the matchee & matcher objects explictly and make them programatically available
<mgz> that sounds reasonable.
<jml> hmm.
<jml> I guess the break there is that if someone sets failureException, assertThat failures become errors.
<jml> I think that's as unlikely to be a problem in practice as third-party mismatches that don't inherit from Mismatch.