diff options
author | Gustavo Niemeyer <gustavo@niemeyer.net> | 2010-09-18 16:36:32 -0300 |
---|---|---|
committer | Gustavo Niemeyer <gustavo@niemeyer.net> | 2010-09-18 16:36:32 -0300 |
commit | f28880cb3cb0642b96732644fc1a4b8c996d5a48 (patch) | |
tree | a8ffbd446282f1992d2b2e11f7acccc7e4e17ef1 | |
parent | 21f0fa2da7fcece8f8ed3125333189e666c66077 (diff) | |
download | mocker-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-- | NEWS | 11 | ||||
-rw-r--r-- | mocker.py | 66 | ||||
-rwxr-xr-x | test.py | 103 |
3 files changed, 165 insertions, 15 deletions
@@ -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) ================= @@ -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 @@ -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 |