summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Niemeyer <gustavo@niemeyer.net>2010-09-18 16:36:32 -0300
committerGustavo Niemeyer <gustavo@niemeyer.net>2010-09-18 16:36:32 -0300
commitf28880cb3cb0642b96732644fc1a4b8c996d5a48 (patch)
treea8ffbd446282f1992d2b2e11f7acccc7e4e17ef1
parent21f0fa2da7fcece8f8ed3125333189e666c66077 (diff)
downloadmocker-f28880cb3cb0642b96732644fc1a4b8c996d5a48.tar.gz
- Implemented support for assertRaises() as a context manager, as in
Python 2.7 and 3.2. - Implemented assertIsInstance() and assertIsNotInstance() as well. - Updated NEWS file.
-rw-r--r--NEWS11
-rw-r--r--mocker.py66
-rwxr-xr-xtest.py103
3 files changed, 165 insertions, 15 deletions
diff --git a/NEWS b/NEWS
index c508df5..53327d8 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,17 @@
function will receive the patched or proxied object so that its state
may be used or verified in checks.
+- assertRaises() in MockerTestCase can now be used like Python 2.7 and 3.2,
+ as a context manager. This enables contructs such as:
+
+ with self.assertRaises(Error):
+ raising_logic()
+
+- Added assertIsInstance() and assertNotIsInstance().
+
+- Fixed bug #634566, reported by Mark Hammond, where throw(Error) effects
+ might make the recorded action be accepted multiple times.
+
1.0 (2010-06-20)
=================
diff --git a/mocker.py b/mocker.py
index eee6c64..4935735 100644
--- a/mocker.py
+++ b/mocker.py
@@ -52,7 +52,7 @@ __all__ = ["Mocker", "Expect", "expect", "IS", "CONTAINS", "IN", "MATCH",
__author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
__license__ = "BSD"
-__version__ = "1.0"
+__version__ = "1.1"
ERROR_PREFIX = "[Mocker] "
@@ -347,7 +347,7 @@ class MockerTestCase(unittest.TestCase):
(first.__name__, name, first_formatted,
second.__name__, name, second_formatted))
- def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
+ def failUnlessRaises(self, excClass, *args, **kwargs):
"""
Fail unless an exception of class excClass is thrown by callableObj
when invoked with arguments args and keyword arguments kwargs. If a
@@ -355,18 +355,55 @@ class MockerTestCase(unittest.TestCase):
test case will be deemed to have suffered an error, exactly as for an
unexpected exception. It returns the exception instance if it matches
the given exception class.
+
+ This may also be used as a context manager when provided with a single
+ argument, as such:
+
+ with self.failUnlessRaises(ExcClass):
+ logic_which_should_raise()
"""
- try:
- result = callableObj(*args, **kwargs)
- except excClass, e:
- return e
+ excName = getattr(excClass, "__name__", str(excClass))
+ if args:
+ callableObj = args[0]
+ try:
+ result = callableObj(*args[1:], **kwargs)
+ except excClass, e:
+ return e
+ else:
+ raise self.failureException("%s not raised (%r returned)" %
+ (self.__class_name(excClass),
+ result))
else:
- excName = excClass
- if hasattr(excClass, "__name__"):
- excName = excClass.__name__
- raise self.failureException(
- "%s not raised (%r returned)" % (excName, result))
-
+ test = self
+ class AssertRaisesContextManager(object):
+ def __enter__(self):
+ return self
+ def __exit__(self, type, value, traceback):
+ self.exception = value
+ if value is None:
+ raise test.failureException("%s not raised" % excName)
+ elif isinstance(value, excClass):
+ return True
+ return AssertRaisesContextManager()
+
+ def __class_name(self, cls):
+ return getattr(cls, "__name__", str(cls))
+
+ def failUnlessIsInstance(self, obj, cls, msg=None):
+ """Assert that isinstance(obj, cls)."""
+ if not isinstance(obj, cls):
+ if msg is None:
+ msg = "%r is not an instance of %s" % \
+ (obj, self.__class_name(cls))
+ raise self.failureException(msg)
+
+ def failIfIsInstance(self, obj, cls, msg=None):
+ """Assert that isinstance(obj, cls) is False."""
+ if isinstance(obj, cls):
+ if msg is None:
+ msg = "%r is an instance of %s" % \
+ (obj, self.__class_name(cls))
+ raise self.failureException(msg)
assertIs = failUnlessIs
assertIsNot = failIfIs
@@ -380,9 +417,8 @@ class MockerTestCase(unittest.TestCase):
assertNotApproximates = failIfApproximates
assertMethodsMatch = failUnlessMethodsMatch
assertRaises = failUnlessRaises
-
- # XXX Add assertIsInstance() and assertIsSubclass, and
- # extend assertRaises() with new logic from unittest.
+ assertIsInstance = failUnlessIsInstance
+ assertNotIsInstance = failIfIsInstance
# The following are missing in Python < 2.4.
assertTrue = unittest.TestCase.failUnless
diff --git a/test.py b/test.py
index c273ed8..d8ed005 100755
--- a/test.py
+++ b/test.py
@@ -891,6 +891,103 @@ class MockerTestCaseTest(TestCase):
else:
self.fail("MyException2 not raised")
+ def test_fail_unless_raises_context_succeeds(self):
+ class MyException(Exception):
+ pass
+ with_manager = self.test.failUnlessRaises(MyException)
+ cm = with_manager.__enter__()
+ self.assertEquals(with_manager.__exit__(MyException,
+ MyException(1, "foo"), None),
+ True)
+ self.assertEquals(cm.exception.args, (1, "foo"))
+
+ def test_fail_unless_raises_context_error(self):
+ with_manager = self.test.failUnlessRaises(ValueError)
+ cm = with_manager.__enter__()
+ try:
+ with_manager.__exit__(None, None, None)
+ except AssertionError, e:
+ self.assertEquals(str(e), "ValueError not raised")
+ self.assertEquals(cm.exception, None)
+ else:
+ self.fail("AssertionError not raised")
+
+ def test_fail_unless_raises_context_other_exception(self):
+ class MyException1(Exception):
+ pass
+ class MyException2(Exception):
+ pass
+ with_manager = self.test.failUnlessRaises(MyException1)
+ cm = with_manager.__enter__()
+ self.assertEquals(with_manager.__exit__(MyException2,
+ MyException2(), None),
+ None)
+ self.assertTrue(isinstance(cm.exception, MyException2))
+
+ def test_fail_unless_is_instance_raises_on_mismatch(self):
+ class C(object):
+ def __repr__(self):
+ return "<C object>"
+ class D(object):
+ pass
+ obj = C()
+ try:
+ self.test.failUnlessIsInstance(obj, D)
+ except AssertionError, e:
+ self.assertEquals(str(e), "<C object> is not an instance of D")
+ else:
+ self.fail("AssertionError not raised")
+
+ def test_fail_unless_is_instance_uses_msg(self):
+ class C(object): pass
+ class D(object): pass
+ obj = C()
+ try:
+ self.test.failUnlessIsInstance(obj, D, "oops!")
+ except AssertionError, e:
+ self.assertEquals(str(e), "oops!")
+ else:
+ self.fail("AssertionError not raised")
+
+ def test_fail_unless_is_instance_succeeds(self):
+ class C(object): pass
+ obj = C()
+ try:
+ self.test.failUnlessIsInstance(obj, C)
+ except AssertionError:
+ self.fail("AssertionError shouldn't be raised")
+
+ def test_fail_if_is_instance_raises_on_mismatch(self):
+ class C(object):
+ def __repr__(self):
+ return "<C object>"
+ obj = C()
+ try:
+ self.test.failIfIsInstance(obj, C)
+ except AssertionError, e:
+ self.assertEquals(str(e), "<C object> is an instance of C")
+ else:
+ self.fail("AssertionError not raised")
+
+ def test_fail_if_is_instance_uses_msg(self):
+ class C(object): pass
+ obj = C()
+ try:
+ self.test.failIfIsInstance(obj, C, "oops!")
+ except AssertionError, e:
+ self.assertEquals(str(e), "oops!")
+ else:
+ self.fail("AssertionError not raised")
+
+ def test_fail_if_is_instance_succeeds(self):
+ class C(object): pass
+ class D(object): pass
+ obj = D()
+ try:
+ self.test.failIfIsInstance(obj, C)
+ except AssertionError:
+ self.fail("AssertionError shouldn't be raised")
+
def test_aliases(self):
get_method = MockerTestCase.__dict__.get
@@ -930,6 +1027,12 @@ class MockerTestCaseTest(TestCase):
self.assertEquals(get_method("assertRaises"),
get_method("failUnlessRaises"))
+ self.assertEquals(get_method("assertIsInstance"),
+ get_method("failUnlessIsInstance"))
+
+ self.assertEquals(get_method("assertNotIsInstance"),
+ get_method("failIfIsInstance"))
+
def test_twisted_trial_aliases(self):
get_method = MockerTestCase.__dict__.get