[TIP] RFC: Post-assertRaises assertions WAS: ANN: unittest2 0.4.0 Release
Olemis Lang
olemis at gmail.com
Fri Apr 9 06:10:30 PDT 2010
On Thu, Apr 8, 2010 at 5:42 PM, Michael Foord <michael at voidspace.org.uk> wrote:
> Hello all,
>
:o)
> I'm pleased to announce the release of version 0.4.0 of unittest2.
>
[...]
>
> For full details of all the new features, see my blog entry:
>
> * http://www.voidspace.org.uk/python/weblog/arch_d7_2010_04_03.shtml#e1171
>
I wanted to know if you have considered support for writing assertions
targeting the exception object been raised . In my experience that is
very helpful when testing some kind of systems. For instance, in Trac
XmlRpcPlugin (<=0.1.6, current trunk ;o) you can find many tests
(actually all TCs checking for error conditions ;o) like this
{{{
#!python
class RpcXmlTestCase(unittest.TestCase):
# Further code omitted ;o)
def test_wrong_argspec(self):
try:
self.admin.system.listMethods("hello")
self.fail("Oops. Wrong argspec accepted???")
except xmlrpclib.Fault, e:
self.assertEquals(2, e.faultCode)
self.assertTrue("listMethods() takes exactly 2 arguments" \
in e.faultString)
}}}
The fact is that the exception object is needed to ensure proper error
codes are returned by the RPC subsystem (and the current protocol
handler under test, plugin is starting to adopt a pluggable
architecture to support multiple RPC protocols ;o). Such assertions on
exc objs will be used quite quite quite often. Nonetheless this
specific style has some drawbacks e.g. assertion for failures are not
explicit, other error conditions are reported as errors rather than
failures, and ...
Therefore, we're recently considering [1]_ (not committed yet ;o) to
adopt this style
{{{
#!python
class TracRpcTestCase(unittest.TestCase):
# Further code omitted ;o)
def assertRaises(self, excClass, callableObj, *args, **kwargs):
"""Enhanced assertions to detect exceptions."""
try:
callableObj(*args, **kwargs)
except excClass, e:
return e
except self.failureException :
raise
except Exception, e :
if hasattr(excClass, '__name__'): excName = excClass.__name__
else: excName = str(excClass)
if hasattr(e, '__name__'): excMsg = e.__name__
else: excMsg = str(e)
raise self.failureException("\n\nExpected %s\n\nGot %s : %s" % (
excName, e.__class__.__name__, excMsg))
else:
if hasattr(excClass,'__name__'): excName = excClass.__name__
else: excName = str(excClass)
raise self.failureException, "Expected %s\n\nNothing
raised" % excName
class RpcXmlTestCase(TracRpcTestCase):
# Further code omitted ;o)
def test_wrong_argspec(self):
def local_test():
self.admin.system.listMethods("hello")
self.fail("Oops. Wrong argspec accepted???")
e = self.assertRaises(xmlrpclib.Fault, local_test)
self.assertEquals(1, e.faultCode)
self.assertTrue("listMethods() takes exactly 2 arguments" \
in e.faultString)
}}}
... using a customized `assertRaises` method that returns the
exception object in order to perform further assertions ;o).
This approach collides with context managers returned by modern
`assertRaises` impl but AFAICS might be extremely useful in situations
like the one I sketched above . Probably would be valuable to consider
support for this in unittest(2) , what d'u think ?
.. [1] TracRpc API v2 patch @ Bb
(http://bitbucket.org/osimons/trac-rpc-mq/src/tip/t5437/t5437-protocol_api_v2-r7194.diff)
--
Regards,
Olemis.
Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/
Featured article:
On adding Hessian (RPC) support for Trac -
http://feedproxy.google.com/~r/simelo-en/~3/Vit6dRudChU/on-adding-hessian-rpc-support-for-trac.html
More information about the testing-in-python
mailing list