classification
Title: unittest.assertRaises() return the raised exception
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.2
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: michael.foord Nosy List: denversc, eric.araujo, kristjan.jonsson, martin.panter, michael.foord
Priority: normal Keywords: patch

Created on 2010-08-13 14:57 by denversc, last changed 2015-01-13 00:38 by martin.panter. This issue is now closed.

Files
File name Uploaded Description Edit
unittest.assertRaises.returnex.v1.patch denversc, 2010-08-13 14:57 Proposed Patch
Messages (7)
msg113781 - (view) Author: Denver Coneybeare (denversc) * Date: 2010-08-13 14:57
It would be great if unittest.assertRaises() returned the raised exception when it passes.  This allows the caller to easily perform further checks on the exception, such as its attribute values.  Currently assertRaises() returns None (when it doesn't return a context manager) so changing the return value should not break backwards compatibility.

I see that this was already discussed in issue6275 but I'd like to resurrect the discussion since this is a common scenario in my unit tests, and I assume others.  Revisions r76238 and r78110 added the ability to get the exception from the context manager (good) but sometimes using the context manager approach adds unnecessary bloat to already long-winded unit tests.

I've attached a possible patch for the py3k branch (unittest.assertRaises.returnex.v1.patch).  Thank you for (re)considering this topic :)  Also, thank you Michael Foord for your recent improvements to unittest... the new features are very much appreciated!
msg113810 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-08-13 18:45
If you want the exception then use assertRaises in a with statement. The exception is available as an attribute on the context manager.
msg113812 - (view) Author: Kristján Valur Jónsson (kristjan.jonsson) * (Python committer) Date: 2010-08-13 18:56
That was a bit abrupt, want't it?  Denver is well aware of this and said: 
"but sometimes using the context manager approach adds unnecessary bloat to already long-winded unit tests."

I happen to agree with him and don't see why we can't discuss this some.  We never did discuss this fully in issue 6275, I just tempered my patch a bit to at least get something done.

I don't think this should be rejected out of hand simply because TBDFL said that its an "'odd' API for a unittest assert method".  assertRaises already return a context manager if called without a callable (an odd api?), and it can just as well return an exception if called _with_ a callable.
msg113813 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-08-13 18:57
Sorry, it's a reopened bug requesting a feature that has already been considered and rejected previously. Yes I was abrupt, my apologies - I'm trying to clear my backlog before I go away.
msg113994 - (view) Author: Denver Coneybeare (denversc) * Date: 2010-08-15 18:53
Michael: Do you disagree with assertRaises() returning the exception object on principle?  Or is this just the consensus that you got from the mailing list, including Guido's comment.  My particular use case is that I want to check certain attributes being set on the raised exception and I feel that the context manager approach is overkill for my tests since it's just one method call in the context manager.  I don't understand why it is considered "odd" for assertRaises() to return the result for further inspection... I need to get it some way and assertRaises() has a reference to it.  Thanks for considering this request further.
msg114015 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-08-15 22:16
Providing access to the exception on the context manager was *precisely* to meet the use case of wanting to make assertions about the exception. I tend to agree with Guido that having one of the asserts return something is a bit odd, but irrespective of that I don't think we should have two ways of doing exactly the same thing. 

In general I find that the with statement version of assertRaises looks a lot better than the old way of calling it, so I guess I also disagree that it is "overkill" or adds bloat.

Sorry guys.
msg114041 - (view) Author: Kristján Valur Jónsson (kristjan.jonsson) * (Python committer) Date: 2010-08-16 09:28
Pehaps it hasn't been demonstrated before, but just for the sake of argument (and because I'm a persistant bugger), here are the two different cases:

current:
ctxt = self.assertRaises(MyException)
with ctxt:
    foo()
self.assertEqual(ctxt.exception.value, 1)

suggested:
e = self.assertRaises(MyExcetpion, foo)
self.assertEqual(e.value, 1)

The inconvenient bit about the current method is having to keep the context manager around.  Also note that the current way of looking at the exception object makes it blatantly clear that self.assertRaises() is returning an object.  That, imho, breaks the argument about self.assert* methods not returning any info.
History
Date User Action Args
2016-09-14 14:44:34r.david.murraylinkissue28135 superseder
2015-01-13 00:38:20martin.pantersetnosy: + martin.panter
2010-11-02 22:06:13eric.araujosetnosy: + eric.araujo
2010-08-16 09:28:24kristjan.jonssonsetmessages: + msg114041
2010-08-15 22:16:37michael.foordsetmessages: + msg114015
2010-08-15 18:53:37denverscsetmessages: + msg113994
2010-08-13 18:57:28michael.foordsetmessages: + msg113813
2010-08-13 18:56:01kristjan.jonssonsetmessages: + msg113812
2010-08-13 18:45:01michael.foordsetstatus: open -> closed
resolution: rejected
messages: + msg113810

stage: resolved
2010-08-13 15:27:38pitrousetassignee: michael.foord
2010-08-13 14:57:42denversccreate