Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Browse files

Fix assertRaises when the exception has a metaclass

Due to not taking into account that the type of the class can be a
subclass of type (which is the case when using metaclasses),
assertRaises would report a false positive in case an exception that was
expected had a custom metaclass.

This patch introduces a more robust checking if a given object is a
class or an instance of one, and adds a test case, to make sure
exceptions with custom metaclasses don't break assertRaises.
  • Loading branch information...
commit 54751af549bbf2b7c780461482bb93b3544377c3 1 parent 877058e
@djipko djipko authored Nikola Dipanov committed
1  LICENSE
@@ -17,6 +17,7 @@ The testtools authors are:
* Gavin Panella
* Martin Pool
* Vincent Ladeuil
+ * Nikola Đipanov
and are collectively referred to as "testtools developers".
2  NEWS
@@ -13,6 +13,8 @@ experimental and we might need to break it.
+* ``assertRaises`` works properly for exception classes that have custom
+ metaclasses
* ``ConcurrentTestSuite`` was silently eating exceptions that propagate from
the method call. Ignoring them is fine in a normal test
4 testtools/matchers/
@@ -44,7 +44,9 @@ def __init__(self, exception, value_re=None):
if istext(value_re):
value_re = AfterPreproccessing(str, MatchesRegex(value_re), False)
self.value_re = value_re
- self._is_instance = type(self.expected) not in classtypes() + (tuple,)
+ expected_type = type(self.expected)
+ self._is_instance = not any(issubclass(expected_type, class_type)
+ for class_type in classtypes() + (tuple,))
def match(self, other):
if type(other) != tuple:
13 testtools/tests/
@@ -302,6 +302,19 @@ def test_assertRaises(self):
# assertRaises asserts that a callable raises a particular exception.
self.assertRaises(RuntimeError, self.raiseError, RuntimeError)
+ def test_assertRaises_exception_w_metaclass(self):
+ # assertRaises works when called for exceptions with custom metaclasses
+ class MyExMeta(type):
+ def __init__(cls, name, bases, dct):
+ """ Do some dummy metaclass stuff """
+ dct.update({'answer': 42})
+ type.__init__(cls, name, bases, dct)
+ class MyEx(Exception):
+ __metaclass__ = MyExMeta
+ self.assertRaises(MyEx, self.raiseError, MyEx)
def test_assertRaises_fails_when_no_error_raised(self):
# assertRaises raises self.failureException when it's passed a
# callable that raises no error.

0 comments on commit 54751af

Please sign in to comment.
Something went wrong with that request. Please try again.