From b64f0d59971eaa6f4d48ac3ebbad7eb867bec5f6 Mon Sep 17 00:00:00 2001 From: Gustavo Niemeyer Date: Sat, 18 Sep 2010 17:36:24 -0300 Subject: Added assertRaisesRegexp() to MockerTestCase. It works similarly to the version in Python 2.7 and 3.2, except it will also return the error found. It also works as a context manager for with: statements. --- NEWS | 6 +++- mocker.py | 35 +++++++++++++++++++-- test.py | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 53327d8..8249f13 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -1.1 (2010-XX-XX) +1.1 (2010-09-18) ================ - mocker.call() now supports a with_object argument. If True, the called @@ -11,6 +11,10 @@ with self.assertRaises(Error): raising_logic() +- Added assertRaisesRegexp() to MockerTestCase. It works similarly to + the version in Python 2.7 and 3.2, except it will also return the error + found. It also works as a context manager for with: statements. + - Added assertIsInstance() and assertNotIsInstance(). - Fixed bug #634566, reported by Mark Hammond, where throw(Error) effects diff --git a/mocker.py b/mocker.py index 4935735..7f7a81a 100644 --- a/mocker.py +++ b/mocker.py @@ -39,6 +39,7 @@ import shutil import types import sys import os +import re import gc @@ -362,17 +363,40 @@ class MockerTestCase(unittest.TestCase): with self.failUnlessRaises(ExcClass): logic_which_should_raise() """ - excName = getattr(excClass, "__name__", str(excClass)) + return self.failUnlessRaisesRegexp(excClass, None, *args, **kwargs) + + def failUnlessRaisesRegexp(self, excClass, regexp, *args, **kwargs): + """ + Fail unless an exception of class excClass is thrown by callableObj + when invoked with arguments args and keyword arguments kwargs, and + the str(error) value matches the provided regexp. If a different type + of exception is thrown, it will not be caught, and the 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.failUnlessRaisesRegexp(ExcClass, "something like.*happened"): + logic_which_should_raise() + """ + def match_regexp(error): + error_str = str(error) + if regexp is not None and not re.search(regexp, error_str): + raise self.failureException("%r doesn't match %r" % + (error_str, regexp)) + excName = self.__class_name(excClass) if args: callableObj = args[0] try: result = callableObj(*args[1:], **kwargs) except excClass, e: + match_regexp(e) return e else: raise self.failureException("%s not raised (%r returned)" % - (self.__class_name(excClass), - result)) + (excName, result)) else: test = self class AssertRaisesContextManager(object): @@ -383,6 +407,7 @@ class MockerTestCase(unittest.TestCase): if value is None: raise test.failureException("%s not raised" % excName) elif isinstance(value, excClass): + match_regexp(value) return True return AssertRaisesContextManager() @@ -417,6 +442,7 @@ class MockerTestCase(unittest.TestCase): assertNotApproximates = failIfApproximates assertMethodsMatch = failUnlessMethodsMatch assertRaises = failUnlessRaises + assertRaisesRegexp = failUnlessRaisesRegexp assertIsInstance = failUnlessIsInstance assertNotIsInstance = failIfIsInstance @@ -890,6 +916,9 @@ class MockerBase(object): """Make the last recorded event cause the given function to be called. @param func: Function to be called. + @param with_object: If True, the called function will receive the + patched or proxied object so that its state may be used or verified + in checks. The result of the function will be used as the event result. """ diff --git a/test.py b/test.py index d8ed005..37ae7b7 100755 --- a/test.py +++ b/test.py @@ -924,6 +924,107 @@ class MockerTestCaseTest(TestCase): None) self.assertTrue(isinstance(cm.exception, MyException2)) + def test_fail_unless_raises_regexp_succeeds(self): + class MyException(Exception): + def __str__(self): + return "Error:" + str(self.args) + def f(*args): + raise MyException(*args) + error = self.test.failUnlessRaisesRegexp(MyException, "rror:.*foo", + f, 1, "foo") + self.assertEquals(error.args, (1, "foo")) + + def test_fail_unless_raises_regexp_doesnt_match(self): + class MyException(Exception): + def __str__(self): + return "Error: " + str(self.args) + def f(*args): + raise MyException(*args) + try: + self.test.failUnlessRaisesRegexp(MyException, "Foo:.*foo", + f, 1, "foo") + except AssertionError, e: + self.assertEquals(str(e), + '"Error: (1, \'foo\')" doesn\'t match ' + '\'Foo:.*foo\'') + else: + self.fail("AssertionError not raised") + + def test_fail_unless_raises_regexp_error(self): + def f(*args): + return args + try: + self.test.failUnlessRaisesRegexp(ValueError, "blah", f, 1, "foo") + except AssertionError, e: + self.assertEquals( + str(e), + "ValueError not raised ((1, 'foo') returned)") + else: + self.fail("AssertionError not raised") + + def test_fail_unless_raises_regexp_other_exception(self): + class MyException1(Exception): + pass + class MyException2(Exception): + pass + def f(*args): + raise MyException2(*args) + try: + self.test.failUnlessRaisesRegexp(MyException1, "blah", f, 1, "foo") + except MyException2: + pass + else: + self.fail("MyException2 not raised") + + def test_fail_unless_raises_regexp_context_succeeds(self): + class MyException(Exception): + def __str__(self): + return "Error: " + str(self.args) + with_manager = self.test.failUnlessRaisesRegexp(MyException, "rror.*f") + 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_regexp_context_doesnt_match(self): + class MyException(Exception): + def __str__(self): + return "Error: " + str(self.args) + with_manager = self.test.failUnlessRaisesRegexp(MyException, "oo.*f") + cm = with_manager.__enter__() + try: + with_manager.__exit__(MyException, MyException(1, "foo"), None) + except AssertionError, e: + self.assertEquals(str(e), + '"Error: (1, \'foo\')" doesn\'t match \'oo.*f\'') + self.assertEquals(cm.exception.args, (1, "foo")) + else: + self.fail("AssertionError not raised") + + def test_fail_unless_raises_regexp_context_error(self): + with_manager = self.test.failUnlessRaisesRegexp(ValueError, "blah") + 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_regexp_context_other_exception(self): + class MyException1(Exception): + pass + class MyException2(Exception): + pass + with_manager = self.test.failUnlessRaisesRegexp(MyException1, "blah") + 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): @@ -1027,6 +1128,9 @@ class MockerTestCaseTest(TestCase): self.assertEquals(get_method("assertRaises"), get_method("failUnlessRaises")) + self.assertEquals(get_method("assertRaisesRegexp"), + get_method("failUnlessRaisesRegexp")) + self.assertEquals(get_method("assertIsInstance"), get_method("failUnlessIsInstance")) -- cgit v1.2.1