This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Better output for unittest
Type: Stage:
Components: Library (Lib) Versions:
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: purcell Nosy List: brett.cannon, gvanrossum, purcell, rhettinger, theller, tim.peters
Priority: normal Keywords: patch

Created on 2003-04-16 17:49 by theller, last changed 2022-04-10 16:08 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
unittest.diff theller, 2003-04-16 17:49 Patch for unittest
unittest-2.diff theller, 2003-04-17 15:31 2nd version of patch
unittest.py.diff theller, 2003-12-05 20:39 unittest-3.diff
test_sample.py theller, 2003-12-05 20:41 test_sample.py
Messages (19)
msg43364 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-04-16 17:49
This patch enables more useful output for unittests: If
a test crashes (raises an unexpected exception), a full
traceback is printed.

If a test failes, the output is something like this:

========================================
FAIL: test_failUnlessEqual (__main__.FailingTests)
----------------------------------------------------------------------
TestFailed: 0 != 1
  File "xunit.py", line 12, in test_failUnlessEqual
    self.failUnlessEqual(self.a, self.b)

========================================

Before, this was printed:

========================================
FAIL: test_failIfEqual (__main__.FailingTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "xunit.py", line 15, in test_failIfEqual
    self.failIfEqual(self.a, self.a)
  File "c:\python23\lib\unittest.py", line 300, in
failIfEqual
    raise self.failureException, \
AssertionError: 0 == 0

========================================

If needed, I can upload the test script I use, together
with the results before and after the patch.

This has shortly been discussed on c.l.p, response was
mostly positive.
http://tinyurl.com/9obf
msg43365 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-04-17 15:31
Logged In: YES 
user_id=11105

Attaching new version of the patch (unittest-2.diff). This
gives better output for failUnlessRaises, like this:

======================================================================
FAIL: test_failUnlessRaises (__main__.FailingTests)
----------------------------------------------------------------------
TestFailed: wrong exception, expected TypeError
got: 'ValueError: 10'
  File "xunit.py", line 18, in test_failUnlessRaises
    self.failUnlessRaises(TypeError, self._raise,
ValueError, 10)

======================================================================
FAIL: test_failUnlessRaises_2 (__main__.FailingTests)
----------------------------------------------------------------------
TestFailed: wrong exception, expected TypeError, IndexError,
or AttributeError
got: 'ValueError: 10'
  File "xunit.py", line 21, in test_failUnlessRaises_2
    self.failUnlessRaises((TypeError, IndexError,
AttributeError), self._raise, ValueError, 10)

----------------------------------------------------------------------
msg43366 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2003-04-20 02:57
Logged In: YES 
user_id=357491

I like the new output, personally.  I am +1 on letting Thomas add the 
changes.
Does this mean we no longer treat unittest as a separate project?
msg43367 - (view) Author: Steve Purcell (purcell) (Python triager) Date: 2003-04-25 11:52
Logged In: YES 
user_id=21477

This behaviour of trimming the traceback was implemented in a previous 
version of PyUnit, but dropped because it did not work with Jython. My 
aim is that the same 'unittest.py' should work out of the box with both 
CPython and Jython. 
msg43368 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-04-25 12:05
Logged In: YES 
user_id=11105

What a pity! What exactly does not work in Jython?

Before giving up on this, there are at least two ways to
proceed:
- Behave as before in Jython, and use the better output in
CPython.
- Apply this patch only the the unittest version bundled
with CPython.

How are the chances for one of this?
msg43369 - (view) Author: Steve Purcell (purcell) (Python triager) Date: 2003-04-25 12:37
Logged In: YES 
user_id=21477

After investigation, this seems to work with Jython (though not JPython, 
which didn't have tb_next etc.). 
 
In general I've been trying hard to keep 'unittest.py' vanilla, since a lot 
of people are still using it with Python 1.5 and even JPython. Hence the 
complete absence of string methods, list comprehensions and other new 
language features. Don't know if this policy makes sense in the longer 
term, but I value it right now. 
 
In that sense, I'm not sure if it's worth changing the message. 
msg43370 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-04-25 12:52
Logged In: YES 
user_id=11105

Last attempt to convince you: I could try to port the
changes to Python 1.5, if you want to stay compatible.

If you still reject the patch (you're the unittest boss),
I'll have to live with subclassing unittest ;-)
msg43371 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2003-05-06 07:11
Logged In: YES 
user_id=80475

I would like to see Thomas's patch or some comformant 
variant go in.  Usability problems are a bug.  Friendlier 
output makes it more likely that unittest will be used in 
the first place.
msg43372 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-05-06 19:52
Logged In: YES 
user_id=31435

I'm split.  The current output when assertRaises fails is a 
frequent cause of head-scratching ("what?  it's complaining 
because ValueError got raised? ... no, it's complaining 
because ValueError wasn't raised? ...").  OTOH, I see no 
value in trimming the traceback.  Now that *could* be 
because the assertRaises output can be so confusing that 
we end up using the rest of the traceback to figure out what 
unittest is trying to tell us in those cases.
msg43373 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-05-06 20:08
Logged In: YES 
user_id=11105

That's exactly how I was feeling. When an assertRaises test
failed, I usually inserted the call it made before this
line, to see the real traceback.

And that's what this patch tries to fix. I don't want to see
tracebacks when a test fails, I want a clear indication that
it failed (the patch prints "TestFailed" instead of
"Traceback:").

For the output of a failed assertRaises, see the first
comment I added. IMO it clearly says what which exception
was expected, and which one was raised.
msg43374 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-05-06 20:27
Logged In: YES 
user_id=31435

That's why I'm split:  I do like the new *messages* better 
(their content), but I don't like losing the tracebacks.  
Sometimes it's a bug in the test driver-- or in 20 layers of test 
driver code --and sometimes it's even a bug in unittest itself.  
The traceback is a fundamental tool when things go wrong, 
so I'm never in favor of hiding parts of tracebacks (hiding could 
be appropriate if you *knew* the true cause isn't in the part 
you're hiding -- but you can't know that).
msg43375 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-10-14 18:05
Logged In: YES 
user_id=11105

Assigned to Steve for pronouncement (didn't he already
comment on python-dev some time ago?)
msg43376 - (view) Author: Steve Purcell (purcell) (Python triager) Date: 2003-10-16 21:32
Logged In: YES 
user_id=21477

I'm looking at all this and will certainly incorporate some of 
the suggestions:  
  
- I'm +1 on the clearer message for assertRaises()  
- I'm +1 on clearer messages for _all_ assert*()/fail*() 
methods  
- The TestFailed exception doesn't really add much, since 
AssertionError works well already  
- I'm loathe to ever suppress tracebacks, or fiddle with them 
much: the traceback is the canonical way for IDEs to find 
lines in the code  
msg43377 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-12-05 20:39
Logged In: YES 
user_id=11105

I've brought the patch up to date with current cvs, and made
small changes: The 'Traceback: most recent call last' line
is no longer removed from the print.  And, according to
Steve's suggestion, AssertionError is used again instead of
the TestFailed exceptiom.

The patch has been discussed in this thread on python-dev:
http://mail.python.org/pipermail/python-dev/2003-December/040623.html

New patch attached: unittest-3.diff
msg43378 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-12-05 20:41
Logged In: YES 
user_id=11105

Attached a test script together with what is printed before
and after the patch:

test_sample.py
msg43379 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2003-12-05 21:40
Logged In: YES 
user_id=6380

I love it!

We're all waiting for a +1 from Steve so this can be checked
into 2.4. (I'd love it in 2.3 too, but that's probably going
to be blocked on the "no new features" rule. :-)
msg43380 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2003-12-05 23:07
Logged In: YES 
user_id=11105

Cool, although after some thought I again like the
TestFailed more than the AssertionError. (But I won't insist)
msg43381 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2003-12-05 23:18
Logged In: YES 
user_id=6380

Thomas, Can you make the TestFailed issue a separate
bug/patch/feature request?
msg43382 - (view) Author: Steve Purcell (purcell) (Python triager) Date: 2003-12-06 13:19
Logged In: YES 
user_id=21477

Hi all, 
 
I've accepted this patch, with some modifications, and checked it into 
both Pyunit and Python CVS. 
 
If the callable passed to assertRaises() throws an exception other than 
the one expected, the test result should really be ERROR; the proposed 
changes to assertRaises() resulted in tracebacks for such unexpected 
exceptions being lost, since only the exception name and message were 
formatted into the failure string. I've therefore left the logic there as it 
was. 
 
Also, rather than hard-code the number of levels of traceback to skip, 
the changes I have checked in automatically determine the number of 
levels to skip. Please take a look and tell me if the trick I have used is 
excessively horrible. 
 
As for the separate TestFailed issue, for me this is not terribly attractive, 
since I know that many people find it very convenient to use the 'assert' 
keyword in their test code. (Note that by setting the 'failureException' 
attribute of your test cases, you can use an exception other than 
AssertionError.) 
 
For your reference, the output of Thomas' sample test script is now as 
follows: 
 
 
FFE 
====================================================================== 
ERROR: test_4 (__main__.MyTestCase) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
  File "heller.py", line 21, in test_4 
    self.assertRaises(ValueError, getattr, self, "spam") 
  File "/export/home/steve/projects/pyunit/pyunit-cvs/unittest.py", line 
319, in failUnlessRaises 
    callableObj(*args, **kwargs) 
AttributeError: 'MyTestCase' object has no attribute 'spam' 
 
====================================================================== 
FAIL: test_1 (__main__.MyTestCase) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
  File "heller.py", line 6, in test_1 
    self.do_this() 
  File "heller.py", line 9, in do_this 
    self.do_that() 
  File "heller.py", line 12, in do_that 
    self.failUnlessEqual(1, 2) 
AssertionError: 1 != 2 
 
====================================================================== 
FAIL: test_3 (__main__.MyTestCase) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
  File "heller.py", line 17, in test_3 
    self.assertRaises(AttributeError, getattr, self, "silly") 
AssertionError: AttributeError not raised 
 
---------------------------------------------------------------------- 
Ran 3 tests in 0.008s 
 
FAILED (failures=2, errors=1) 
 
History
Date User Action Args
2022-04-10 16:08:10adminsetgithub: 38312
2003-04-16 17:49:36thellercreate