#!/usr/bin/python import unittest import tempfile import inspect import shutil import sys import os from types import ModuleType try: import coverage except ImportError: coverage = None else: # Start coverage check before importing from mocker, to get all of it. coverage.erase() coverage.start() from mocker import \ MockerBase, Mocker, Mock, Event, Task, Action, Path, recorder, expect, \ PathMatcher, path_matcher_recorder, RunCounter, ImplicitRunCounter, \ run_counter_recorder, run_counter_removal_recorder, MockReturner, \ mock_returner_recorder, FunctionRunner, Orderer, SpecChecker, \ spec_checker_recorder, match_params, ANY, IS, CONTAINS, IN, MATCH, ARGS, \ KWARGS, MatchError, PathExecuter, ProxyReplacer, Patcher, Undefined, \ PatchedMethod, MockerTestCase, ReplayRestoreEvent, OnRestoreCaller, Expect class TestCase(unittest.TestCase): """Python 2.3 lacked a couple of useful aliases.""" assertTrue = unittest.TestCase.failUnless assertFalse = unittest.TestCase.failIf class CleanMocker(MockerBase): """Just a better name for MockerBase in a testing context.""" class IntegrationTest(TestCase): def setUp(self): self.mocker = Mocker() def tearDown(self): self.mocker.restore() def test_count(self): obj = self.mocker.mock() obj.x self.mocker.count(2, 3) self.mocker.replay() obj.x self.assertRaises(AssertionError, self.mocker.verify) obj.x self.mocker.verify() obj.x self.mocker.verify() self.assertRaises(AssertionError, getattr, obj, "x") def test_order(self): obj = self.mocker.mock() with_manager = self.mocker.order() with_manager.__enter__() obj.x obj.y obj.z with_manager.__exit__(None, None, None) self.mocker.replay() self.assertRaises(AssertionError, getattr, obj, "y") self.assertRaises(AssertionError, getattr, obj, "z") self.mocker.replay() obj.x self.assertRaises(AssertionError, getattr, obj, "z") self.mocker.replay() obj.x obj.y obj.z def test_spec_and_type(self): class C(object): def m(self, a): pass obj = self.mocker.mock(C) obj.m(1) obj.m(a=1) obj.m(1, 2) obj.m(b=2) obj.x() obj.y() self.mocker.nospec() obj.z() self.mocker.replay() self.assertTrue(isinstance(obj, C)) obj.m(1) obj.m(a=1) obj.y() self.assertRaises(AssertionError, obj.m, 1, 2) self.assertRaises(AssertionError, obj.m, b=2) self.assertRaises(AssertionError, obj.x) self.assertRaises(AssertionError, obj.z) def test_result(self): obj = self.mocker.mock() obj.x self.mocker.result(42) self.mocker.replay() self.assertEquals(obj.x, 42) def test_throw(self): obj = self.mocker.mock() obj.x() self.mocker.throw(ValueError) self.mocker.replay() self.assertRaises(ValueError, obj.x) self.assertRaises(AssertionError, obj.x) def test_throw_with_count(self): """ This ensures that the count problem is reported correctly even when using an explicit count. If the ordering of problems isn't handled properly, the thrown error might surface before the count one. """ obj = self.mocker.mock() obj.x() self.mocker.throw(ValueError) self.mocker.count(2) self.mocker.replay() self.assertRaises(ValueError, obj.x) self.assertRaises(ValueError, obj.x) self.assertRaises(AssertionError, obj.x) def test_call(self): calls = [] def func(arg): calls.append(arg) return 42 obj = self.mocker.mock() obj.x(24) self.mocker.call(func) self.mocker.replay() self.assertEquals(obj.x(24), 42) self.assertEquals(calls, [24]) def test_call_result(self): calls = [] def func(arg): calls.append(arg) return arg obj = self.mocker.mock() obj.x(24) self.mocker.call(func) self.mocker.result(42) self.mocker.replay() self.assertEquals(obj.x(24), 42) self.assertEquals(calls, [24]) def test_call_with_object(self): class C(object): def method(self, a, b, c): return "Running real method?" calls = [] def func(*args, **kwargs): calls.append(args) calls.append(kwargs) return 4 mock = self.mocker.patch(C) mock.method(1, 2, c=3) self.mocker.call(func, with_object=True) self.mocker.replay() obj = C() self.assertEquals(obj.method(1, 2, c=3), 4) # Mocked. self.assertEquals(calls, [(obj, 1, 2), {"c": 3}]) def test_generate(self): obj = self.mocker.mock() obj.x(24) self.mocker.generate([1, 2, 3]) self.mocker.replay() result = obj.x(24) def g(): yield None self.assertEquals(type(result), type(g())) self.assertEquals(list(result), [1, 2, 3]) def test_proxy(self): class C(object): def sum(self, *args): return sum(args) obj = self.mocker.proxy(C()) expect(obj.multiply(2, 3)).result(6).nospec() expect(obj.sum(0, 0)).result(1) expect(obj.sum(0, 0)).passthrough() self.mocker.replay() self.assertEquals(obj.multiply(2, 3), 6) # Mocked. self.assertRaises(AttributeError, obj.multiply) # Passed through. self.assertEquals(obj.sum(2, 3), 5) # Passed through. self.assertEquals(obj.sum(0, 0), 1) # Mocked. self.assertEquals(obj.sum(0, 0), 0) # Passed through explicitly. self.assertRaises(AssertionError, obj.sum, 0, 0) # Seen twice. def test_replace_install_and_restore(self): module = self.mocker.replace("calendar") import calendar self.assertTrue(calendar is not module) self.mocker.replay() import calendar self.assertTrue(calendar is module) self.mocker.restore() import calendar self.assertTrue(calendar is not module) def test_replace_os_path_join(self): path = self.mocker.replace("os.path") expect(path.join(ARGS)).call(lambda *args: "-".join(args)) expect(path.join("e", ARGS)).passthrough() self.mocker.replay() self.assertEquals(os.path.join("a", "b", "c"), "a-b-c") self.assertNotEquals(os.path.join("e", "f", "g"), "e-f-g") def test_replace_os_path_isfile(self): path = self.mocker.replace("os.path") expect(path.isfile("unexistent")).result(True) expect(path.isfile(ANY)).passthrough().count(2) self.mocker.replay() self.assertFalse(os.path.isfile("another-unexistent")) self.assertTrue(os.path.isfile("unexistent")) self.assertFalse(os.path.isfile("unexistent")) def test_replace_class_method(self): empty = self.mocker.replace("Queue.Queue.empty") expect(empty()).result(False) self.mocker.replay() from Queue import Queue self.assertEquals(Queue().empty(), False) def test_patch_with_spec(self): class C(object): def method(self, a, b): pass mock = self.mocker.patch(C) mock.method(1, 2) mock.method(1) self.mocker.replay() mock.method(1, 2) self.assertRaises(AssertionError, mock.method, 1) def test_patch_with_spec_and_unexistent(self): class C(object): pass mock = self.mocker.patch(C) mock.method(1, 2) self.mocker.count(0) self.mocker.replay() self.assertRaises(AssertionError, self.mocker.verify) def test_mock_iter(self): """ list() uses len() as a hint. When we mock iter(), it shouldn't explode due to the lack of len(). """ mock = self.mocker.mock() iter(mock) self.mocker.result(iter([1, 2, 3])) self.mocker.replay() self.assertEquals(list(mock), [1, 2, 3]) self.mocker.verify() def test_replace_builtin_function(self): """ Inspection doesn't work on builtin functions, but proxying should work even then (without spec enforcement in these cases). """ from zlib import adler32 mock = self.mocker.proxy(adler32) mock() self.mocker.result(42) self.mocker.replay() self.assertEquals(mock(), 42) class ExpectTest(TestCase): def setUp(self): self.mocker = CleanMocker() def test_calling_mocker(self): obj = self.mocker.mock() expect(obj.attr).result(123) self.mocker.replay() self.assertEquals(obj.attr, 123) def test_chaining(self): obj = self.mocker.mock() expect(obj.attr).result(123).result(42) self.mocker.replay() self.assertEquals(obj.attr, 42) def test_explicit_expect_instance(self): obj = self.mocker.mock() myexpect = Expect(self.mocker) myexpect(iter(obj)).generate([1, 2, 3]).count(1, 2) self.mocker.replay() self.assertEquals(list(obj), [1, 2, 3]) class MockerTestCaseTest(TestCase): def setUp(self): self.test = MockerTestCase("shortDescription") def tearDown(self): self.test.mocker.restore() # Run it so that any cleanups are performed. self.test.run() def test_has_mocker(self): self.assertEquals(type(self.test.mocker), Mocker) def test_has_expect(self): self.assertTrue(issubclass(self.test.expect, expect)) def test_expect_works_with_non_mocks(self): # We must be using the Expect helper for this to work at all: obj = self.test.mocker.mock() self.test.expect(iter(obj)).generate([1,2,3]) def test_attributes_are_the_same(self): class MyTest(MockerTestCase): def test_method(self): pass test_method.foo = "bar" test = MyTest("test_method") self.assertEquals(getattr(test.test_method, "im_class", None), MyTest) self.assertEquals(getattr(test.test_method, "foo", None), "bar") def test_constructor_is_the_same(self): self.assertEquals(inspect.getargspec(TestCase.__init__), inspect.getargspec(MockerTestCase.__init__)) def test_docstring_is_the_same(self): class MyTest(MockerTestCase): def test_method(self): """Hello there!""" self.assertEquals(MyTest("test_method").test_method.__doc__, "Hello there!") def test_short_description_is_the_same(self): class MyTest(MockerTestCase): def test_method(self): """Hello there!""" class StandardTest(TestCase): def test_method(self): """Hello there!""" self.assertEquals(MyTest("test_method").shortDescription(), StandardTest("test_method").shortDescription()) def test_missing_method_raises_the_same_error(self): class MyTest(TestCase): pass try: MyTest("unexistent_method").run() except Exception, e: expected_error = e class MyTest(MockerTestCase): pass try: MyTest("unexistent_method").run() except Exception, e: self.assertEquals(str(e), str(expected_error)) self.assertEquals(type(e), type(expected_error)) def test_raises_runtime_error_if_not_in_replay_mode_with_events(self): class MyTest(MockerTestCase): def test_method(self): pass test = MyTest("test_method") # That's fine. test.test_method() test.mocker.add_event(Event()) # That's not. self.assertRaises(RuntimeError, test.test_method) test.mocker.replay() # Fine again. test.test_method() def test_mocker_is_verified_and_restored_after_test_method_is_run(self): calls = [] class MyEvent(Event): def verify(self): calls.append("verify") def restore(self): calls.append("restore") class MyTest(MockerTestCase): def test_method(self): self.mocker.add_event(MyEvent()) self.mocker.replay() def test_method_raising(self): self.mocker.add_event(MyEvent()) self.mocker.replay() raise AssertionError("BOOM!") result = unittest.TestResult() MyTest("test_method").run(result) self.assertEquals(calls, ["verify", "restore"]) self.assertTrue(result.wasSuccessful()) del calls[:] result = unittest.TestResult() MyTest("test_method_raising").run(result) self.assertEquals(calls, ["restore"]) self.assertEquals(len(result.errors), 0) self.assertEquals(len(result.failures), 1) self.assertTrue("BOOM!" in result.failures[0][1]) del calls[:] result = unittest.TestResult() # Running twice in the same instance (Trial does that). test = MyTest("test_method") test.run(result) test.run(result) self.assertEquals(calls, ["verify", "restore", "verify", "restore"]) self.assertTrue(result.wasSuccessful()) def test_expectation_failure_acts_appropriately(self): class MyTest(MockerTestCase): def test_method(self): mock = self.mocker.mock() mock.x self.mocker.replay() result = unittest.TestResult() MyTest("test_method").run(result) self.assertEquals(len(result.errors), 0) self.assertEquals(len(result.failures), 1) self.assertTrue("mock.x" in result.failures[0][1]) def test_add_cleanup(self): stash = [] def func(a, b): stash.append((a, b)) class MyTest(MockerTestCase): def tearDown(self): self.addCleanup(func, 3, b=4) def test_method(self): self.addCleanup(func, 1, b=2) stash.append(stash[:]) MyTest("test_method").run() self.assertEquals(stash, [[], (1, 2), (3, 4)]) def test_cleanup_wrapper_in__call__for_2_3(self): version_info = sys.version_info __call__ = unittest.TestCase.__call__ try: sys.version_info = (2, 3, 5) stash = [] def call(self, *args, **kwargs): self.addCleanup(lambda: stash.append(True)) unittest.TestCase.__call__ = call class MyTest(MockerTestCase): def test_method(self): pass MyTest("test_method")() self.assertEquals(stash, [True]) finally: unittest.TestCase.__call__ = __call__ sys.version_info = version_info def test_cleanup_wrapper_in__call__for_2_4(self): version_info = sys.version_info __call__ = unittest.TestCase.__call__ try: sys.version_info = (2, 4) stash = [] def call(self, *args, **kwargs): self.addCleanup(lambda: stash.append(True)) unittest.TestCase.__call__ = call class MyTest(MockerTestCase): def test_method(self): pass MyTest("test_method")() # Python 2.4+ handles cleanup in run(), registered inside # MockerTestCase.__init__, so this should *not* work. self.assertEquals(stash, []) finally: unittest.TestCase.__call__ = __call__ sys.version_info = version_info def test_twisted_trial_deferred_support(self): calls = [] callbacks = [] errbacks = [] deferreds = [] class Deferred(object): def addCallback(self, callback): callbacks.append(callback) def addErrback(self, errback): errbacks.append(errback) class MyEvent(Event): def verify(self): calls.append("verify") def restore(self): calls.append("restore") class MyTest(MockerTestCase): def test_method(self): self.mocker.add_event(MyEvent()) self.mocker.replay() deferred = Deferred() deferreds.append(deferred) return deferred result = unittest.TestResult() test = MyTest("test_method") deferred = test.test_method() self.assertEquals(deferred, deferreds[-1]) self.assertEquals(calls, []) self.assertEquals(len(callbacks), 1) self.assertEquals(callbacks[-1]("foo"), "foo") self.assertEquals(calls, ["verify"]) def test_fail_unless_is_raises_on_mismatch(self): try: self.test.failUnlessIs([], []) except AssertionError, e: self.assertEquals(str(e), "[] is not []") else: self.fail("AssertionError not raised") def test_fail_unless_is_uses_msg(self): try: self.test.failUnlessIs([], [], "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_unless_is_succeeds(self): obj = [] try: self.test.failUnlessIs(obj, obj) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_if_is_raises_on_mismatch(self): obj = [] try: self.test.failIfIs(obj, obj) except AssertionError, e: self.assertEquals(str(e), "[] is []") else: self.fail("AssertionError not raised") def test_fail_if_is_uses_msg(self): obj = [] try: self.test.failIfIs(obj, obj, "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_if_is_succeeds(self): try: self.test.failIfIs([], []) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_unless_in_raises_on_mismatch(self): try: self.test.failUnlessIn(1, []) except AssertionError, e: self.assertEquals(str(e), "1 not in []") else: self.fail("AssertionError not raised") def test_fail_unless_in_uses_msg(self): try: self.test.failUnlessIn(1, [], "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_unless_in_succeeds(self): try: self.test.failUnlessIn(1, [1]) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_if_in_raises_on_mismatch(self): try: self.test.failIfIn(1, [1]) except AssertionError, e: self.assertEquals(str(e), "1 in [1]") else: self.fail("AssertionError not raised") def test_fail_if_in_uses_msg(self): try: self.test.failIfIn(1, [1], "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_if_in_succeeds(self): try: self.test.failIfIn(1, []) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_unless_starts_with_raises_on_mismatch(self): try: self.test.failUnlessStartsWith("abc", "def") except AssertionError, e: self.assertEquals(str(e), "'abc' doesn't start with 'def'") else: self.fail("AssertionError not raised") def test_fail_unless_starts_with_uses_msg(self): try: self.test.failUnlessStartsWith("abc", "def", "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_unless_starts_with_succeeds(self): try: self.test.failUnlessStartsWith("abcdef", "abc") except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_unless_starts_with_works_with_non_strings(self): self.test.failUnlessStartsWith([1, 2, 3], [1, 2]) self.assertRaises(AssertionError, self.test.failUnlessStartsWith, [1, 2, 3], [4, 5, 6]) def test_fail_if_starts_with_raises_on_mismatch(self): try: self.test.failIfStartsWith("abcdef", "abc") except AssertionError, e: self.assertEquals(str(e), "'abcdef' starts with 'abc'") else: self.fail("AssertionError not raised") def test_fail_if_starts_with_uses_msg(self): try: self.test.failIfStartsWith("abcdef", "abc", "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_if_starts_with_succeeds(self): try: self.test.failIfStartsWith("abc", "def") except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_if_starts_with_works_with_non_strings(self): self.test.failIfStartsWith([1, 2, 3], [4, 5, 6]) self.assertRaises(AssertionError, self.test.failIfStartsWith, [1, 2, 3], [1, 2]) def test_fail_unless_ends_with_raises_on_mismatch(self): try: self.test.failUnlessEndsWith("abc", "def") except AssertionError, e: self.assertEquals(str(e), "'abc' doesn't end with 'def'") else: self.fail("AssertionError not raised") def test_fail_unless_ends_with_uses_msg(self): try: self.test.failUnlessEndsWith("abc", "def", "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_unless_ends_with_succeeds(self): try: self.test.failUnlessEndsWith("abcdef", "def") except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_unless_ends_with_works_with_non_strings(self): self.test.failUnlessEndsWith([1, 2, 3], [2, 3]) self.assertRaises(AssertionError, self.test.failUnlessEndsWith, [1, 2, 3], [4, 5, 6]) def test_fail_if_ends_with_raises_on_mismatch(self): try: self.test.failIfEndsWith("abcdef", "def") except AssertionError, e: self.assertEquals(str(e), "'abcdef' ends with 'def'") else: self.fail("AssertionError not raised") def test_fail_if_ends_with_uses_msg(self): try: self.test.failIfEndsWith("abcdef", "def", "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_if_ends_with_succeeds(self): try: self.test.failIfEndsWith("abc", "def") except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_if_ends_with_works_with_non_strings(self): self.test.failIfEndsWith([1, 2, 3], [4, 5, 6]) self.assertRaises(AssertionError, self.test.failIfEndsWith, [1, 2, 3], [2, 3]) def test_fail_unless_approximates_raises_on_mismatch(self): try: self.test.failUnlessApproximates(1, 2, 0.999) except AssertionError, e: self.assertEquals(str(e), "abs(1 - 2) > 0.999") else: self.fail("AssertionError not raised") def test_fail_unless_approximates_uses_msg(self): try: self.test.failUnlessApproximates(1, 2, 0.999, "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_unless_approximates_succeeds(self): try: self.test.failUnlessApproximates(1, 2, 1) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_if_approximates_raises_on_mismatch(self): try: self.test.failIfApproximates(1, 2, 1) except AssertionError, e: self.assertEquals(str(e), "abs(1 - 2) <= 1") else: self.fail("AssertionError not raised") def test_fail_if_approximates_uses_msg(self): try: self.test.failIfApproximates(1, 2, 1, "oops!") except AssertionError, e: self.assertEquals(str(e), "oops!") else: self.fail("AssertionError not raised") def test_fail_if_approximates_succeeds(self): try: self.test.failIfApproximates(1, 2, 0.999) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_unless_methods_match_raises_on_different_method(self): class Fake(object): def method(self, a): pass class Real(object): def method(self, b): pass try: self.test.failUnlessMethodsMatch(Fake, Real) except AssertionError, e: self.assertEquals(str(e), "Fake.method(self, a) != " "Real.method(self, b)") else: self.fail("AssertionError not raised") def test_fail_unless_methods_match_raises_on_missing_method(self): class Fake(object): def method(self, a): pass class Real(object): pass try: self.test.failUnlessMethodsMatch(Fake, Real) except AssertionError, e: self.assertEquals(str(e), "Fake.method(self, a) not present " "in Real") else: self.fail("AssertionError not raised") def test_fail_unless_methods_match_succeeds_on_missing_priv_method(self): class Fake(object): def _method(self, a): pass class Real(object): pass try: self.test.failUnlessMethodsMatch(Fake, Real) except AssertionError, e: self.fail("AssertionError shouldn't be raised") def test_fail_unless_methods_match_raises_on_different_priv_method(self): class Fake(object): def _method(self, a): pass class Real(object): def _method(self, b): pass try: self.test.failUnlessMethodsMatch(Fake, Real) except AssertionError, e: self.assertEquals(str(e), "Fake._method(self, a) != " "Real._method(self, b)") else: self.fail("AssertionError not raised") def test_fail_unless_methods_match_succeeds(self): class Fake(object): def method(self, a): pass class Real(object): def method(self, a): pass obj = [] try: self.test.failUnlessMethodsMatch(Fake, Real) except AssertionError: self.fail("AssertionError shouldn't be raised") def test_fail_unless_raises_succeeds(self): class MyException(Exception): pass def f(*args): raise MyException(*args) error = self.test.failUnlessRaises(MyException, f, 1, "foo") self.assertEquals(error.args, (1, "foo")) def test_fail_unless_raises_error(self): def f(*args): return args try: self.test.failUnlessRaises(ValueError, 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_other_exception(self): class MyException1(Exception): pass class MyException2(Exception): pass def f(*args): raise MyException2(*args) try: self.test.failUnlessRaises(MyException1, f, 1, "foo") except MyException2: pass 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_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): return "" class D(object): pass obj = C() try: self.test.failUnlessIsInstance(obj, D) except AssertionError, e: self.assertEquals(str(e), " 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 "" obj = C() try: self.test.failIfIsInstance(obj, C) except AssertionError, e: self.assertEquals(str(e), " 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 self.assertEquals(get_method("assertIs"), get_method("failUnlessIs")) self.assertEquals(get_method("assertIsNot"), get_method("failIfIs")) self.assertEquals(get_method("assertIn"), get_method("failUnlessIn")) self.assertEquals(get_method("assertNotIn"), get_method("failIfIn")) self.assertEquals(get_method("assertStartsWith"), get_method("failUnlessStartsWith")) self.assertEquals(get_method("assertNotStartsWith"), get_method("failIfStartsWith")) self.assertEquals(get_method("assertEndsWith"), get_method("failUnlessEndsWith")) self.assertEquals(get_method("assertNotEndsWith"), get_method("failIfEndsWith")) self.assertEquals(get_method("assertApproximates"), get_method("failUnlessApproximates")) self.assertEquals(get_method("assertNotApproximates"), get_method("failIfApproximates")) self.assertEquals(get_method("assertMethodsMatch"), get_method("failUnlessMethodsMatch")) self.assertEquals(get_method("assertRaises"), get_method("failUnlessRaises")) self.assertEquals(get_method("assertRaisesRegexp"), get_method("failUnlessRaisesRegexp")) self.assertEquals(get_method("assertIsInstance"), get_method("failUnlessIsInstance")) self.assertEquals(get_method("assertIsNotInstance"), get_method("failIfIsInstance")) # Poor choice in Python 2.7/3.2+. self.assertEquals(get_method("assertNotIsInstance"), get_method("failIfIsInstance")) def test_twisted_trial_aliases(self): get_method = MockerTestCase.__dict__.get self.assertEquals(get_method("assertIdentical"), get_method("assertIs")) self.assertEquals(get_method("assertNotIdentical"), get_method("assertIsNot")) self.assertEquals(get_method("failUnlessIdentical"), get_method("failUnlessIs")) self.assertEquals(get_method("failIfIdentical"), get_method("failIfIs")) def test_missing_python23_aliases(self): self.assertEquals(MockerTestCase.assertTrue.im_func, MockerTestCase.failUnless.im_func) self.assertEquals(MockerTestCase.assertFalse.im_func, MockerTestCase.failIf.im_func) def test_make_file_returns_writable_filename(self): filename = self.test.makeFile() self.assertFalse(os.path.isfile(filename)) open(filename, "w").write("Is writable!") def test_make_file_creates_file(self): filename = self.test.makeFile("") self.assertEquals(os.path.getsize(filename), 0) def test_make_file_cleansup_on_success(self): filename = self.test.makeFile() self.test.run() self.assertEquals(os.path.isfile(filename), False) def test_make_file_cleansup_on_failure(self): class MyTest(MockerTestCase): def test_method(self): raise AssertionError("BOOM!") test = MyTest("test_method") filename = test.makeFile() test.run() self.assertEquals(os.path.isfile(filename), False) def test_make_file_with_content(self): filename = self.test.makeFile("content") self.assertEquals(open(filename).read(), "content") def test_make_file_with_prefix(self): filename = self.test.makeFile(prefix="prefix-") self.assertTrue(os.path.basename(filename).startswith("prefix-")) def test_make_file_with_suffix(self): filename = self.test.makeFile(suffix="-suffix") self.assertTrue(os.path.basename(filename).endswith("-suffix")) def test_make_file_with_dirname(self): dirname = tempfile.mkdtemp() try: filename = self.test.makeFile(dirname=dirname) self.assertEquals(os.path.dirname(filename), dirname) finally: shutil.rmtree(dirname) def test_make_file_with_basename(self): filename = self.test.makeFile(basename="basename") self.assertEquals(os.path.basename(filename), "basename") self.test.run() self.assertFalse(os.path.exists(filename)) def test_make_file_with_basename_and_dirname(self): dirname = tempfile.mkdtemp() try: filename = self.test.makeFile(dirname=dirname, basename="basename") self.assertEquals(os.path.dirname(filename), dirname) self.assertEquals(os.path.basename(filename), "basename") finally: shutil.rmtree(dirname) def test_make_file_with_path(self): path = tempfile.mktemp() try: filename = self.test.makeFile("", path=path) self.assertEquals(filename, path) self.assertEquals(os.path.getsize(filename), 0) self.test.run() self.assertFalse(os.path.exists(filename)) finally: if os.path.isfile(path): os.unlink(path) def test_make_dir_returns_dirname(self): dirname = self.test.makeDir() self.assertEquals(os.path.isdir(dirname), True) def test_make_dir_cleansup_on_success(self): dirname = self.test.makeDir() self.test.run() self.assertEquals(os.path.isdir(dirname), False) def test_make_dir_cleansup_on_failure(self): class MyTest(MockerTestCase): def test_method(self): raise AssertionError("BOOM!") test = MyTest("test_method") dirname = test.makeDir() test.run() self.assertEquals(os.path.isdir(dirname), False) def test_make_dir_with_prefix(self): dirname = self.test.makeDir(prefix="prefix-") self.assertTrue(os.path.basename(dirname).startswith("prefix-")) def test_make_dir_with_suffix(self): dirname = self.test.makeDir(suffix="-suffix") self.assertTrue(os.path.basename(dirname).endswith("-suffix")) def test_make_dir_with_dirname(self): dirname = tempfile.mkdtemp() try: path = self.test.makeDir(dirname=dirname) self.assertEquals(os.path.dirname(path), dirname) finally: if os.path.exists(dirname): shutil.rmtree(dirname) def test_make_dir_with_path(self): path = tempfile.mktemp() try: self.assertEquals(self.test.makeDir(path=path), path) self.assertEquals(os.path.isdir(path), True) self.test.run() self.assertEquals(os.path.isdir(path), False) finally: if os.path.exists(path): shutil.rmtree(path) def test_mocker_is_restored_between_method_return_and_cleanup(self): """ Certain base classes which MockerTestCase is mixed with may have additional logic after the real test method is run, but before run() returns. We don't want to perform mocking checks on these. """ class CustomTestCase(unittest.TestCase): def run(self, result): import time super(CustomTestCase, self).run(result) self.assertTrue(time.time()) class MyTest(CustomTestCase, MockerTestCase): def test_method(self): import time time_mock = self.mocker.replace(time.time) time_mock() self.mocker.count(0) # Forbit it entirely. self.mocker.replay() result = unittest.TestResult() MyTest("test_method").run(result) self.assertEquals(result.errors, []) self.assertEquals(result.failures, []) class MockerTest(TestCase): def setUp(self): self.recorded = [] self.mocker = CleanMocker() def myrecorder(mocker, event): self.recorded.append((mocker, event)) self.mocker.add_recorder(myrecorder) self.action = Action("getattr", ("attr",), {}, Path(Mock(self.mocker, name="mock"))) self.path = self.action.path + self.action def test_default_is_recording(self): self.assertTrue(self.mocker.is_recording()) def test_replay(self): calls = [] event = self.mocker.add_event(Event()) task = event.add_task(Task()) task.replay = lambda: calls.append("replay") task.restore = lambda: calls.append("restore") self.mocker.replay() self.assertFalse(self.mocker.is_recording()) self.assertEquals(calls, ["replay"]) self.mocker.replay() self.assertEquals(calls, ["replay", "restore", "replay"]) def test_restore(self): calls = [] event = self.mocker.add_event(Event()) task = event.add_task(Task()) task.replay = lambda: calls.append("replay") task.restore = lambda: calls.append("restore") self.mocker.replay() self.mocker.restore() self.mocker.restore() self.assertTrue(self.mocker.is_recording()) self.assertEquals(calls, ["replay", "restore"]) def test_reset(self): calls = [] event = self.mocker.add_event(Event()) task = event.add_task(Task()) task.restore = lambda: calls.append("restore") self.mocker.replay() self.mocker.reset() self.mocker.reset() self.assertEquals(calls, ["restore"]) self.assertEquals(self.mocker.get_events(), []) def test_reset_removes_ordering(self): self.mocker.order() self.mocker.reset() self.assertFalse(self.mocker.is_ordering()) def test_verify(self): class MyEvent(object): def __init__(self, id, failed): self.id = id self.failed = failed def verify(self): if self.failed: raise AssertionError("%d failed\n- Line 1\n- Line 2\n" % self.id) self.mocker.add_event(MyEvent(1, True)) self.mocker.add_event(MyEvent(2, False)) self.mocker.add_event(MyEvent(3, True)) try: self.mocker.verify() except AssertionError, e: message = os.linesep.join(["[Mocker] Unmet expectations:", "", "=> 1 failed", " - Line 1", " - Line 2", "", "=> 3 failed", " - Line 1", " - Line 2", ""]) self.assertEquals(str(e), message) else: self.fail("AssertionError not raised") def test_verify_errors_need_good_messages(self): class MyEvent(object): def verify(self): raise AssertionError() self.mocker.add_event(MyEvent()) self.assertRaises(RuntimeError, self.mocker.verify) def test_mocker_as_context_manager(self): calls = [] throw = False class MyEvent(Event): def verify(self): calls.append("verify") if throw: raise AssertionError("Some problem") def replay(self): calls.append("replay") def restore(self): calls.append("restore") event = MyEvent() self.mocker.add_event(event) self.assertEquals(calls, []) mocker = self.mocker.__enter__() self.assertTrue(mocker is self.mocker) self.assertEquals(calls, ["replay"]) # Verify without errors. del calls[:] result = self.mocker.__exit__(None, None, None) self.assertEquals(result, False) self.assertEquals(calls, ["restore", "verify"]) throw = True # Verify raising an error. self.mocker.replay() del calls[:] self.assertRaises(AssertionError, self.mocker.__exit__, None, None, None) self.assertEquals(calls, ["restore", "verify"]) # An exception happened in the 'with' block. Verify won't raise. self.mocker.replay() del calls[:] result = self.mocker.__exit__(AssertionError, None, None) self.assertEquals(result, False) self.assertEquals(calls, ["restore"]) def test_add_recorder_on_instance(self): obj1 = object() obj2 = object() mocker = CleanMocker() self.assertEquals(mocker.add_recorder(obj1), obj1) self.assertEquals(mocker.add_recorder(obj2), obj2) self.assertEquals(mocker.get_recorders(), [obj1, obj2]) mocker = CleanMocker() self.assertEquals(mocker.add_recorder(obj1), obj1) self.assertEquals(mocker.get_recorders(), [obj1]) def test_add_recorder_on_class(self): class MyMocker(CleanMocker): pass obj1 = object() obj2 = object() self.assertEquals(MyMocker.add_recorder(obj1), obj1) self.assertEquals(MyMocker.add_recorder(obj2), obj2) mocker = MyMocker() self.assertEquals(mocker.get_recorders(), [obj1, obj2]) mocker = MyMocker() self.assertEquals(mocker.get_recorders(), [obj1, obj2]) def test_add_recorder_on_subclass(self): class MyMocker1(CleanMocker): pass obj1 = object() MyMocker1.add_recorder(obj1) class MyMocker2(MyMocker1): pass obj2 = object() MyMocker2.add_recorder(obj2) self.assertEquals(MyMocker1.get_recorders(), [obj1]) self.assertEquals(MyMocker2.get_recorders(), [obj1, obj2]) def test_remove_recorder_on_instance(self): obj1 = object() obj2 = object() obj3 = object() class MyMocker(CleanMocker): pass MyMocker.add_recorder(obj1) MyMocker.add_recorder(obj2) MyMocker.add_recorder(obj3) mocker = MyMocker() mocker.remove_recorder(obj2) self.assertEquals(mocker.get_recorders(), [obj1, obj3]) self.assertEquals(MyMocker.get_recorders(), [obj1, obj2, obj3]) def test_remove_recorder_on_class(self): class MyMocker(CleanMocker): pass obj1 = object() obj2 = object() self.assertEquals(MyMocker.add_recorder(obj1), obj1) self.assertEquals(MyMocker.add_recorder(obj2), obj2) MyMocker.remove_recorder(obj1) self.assertEquals(MyMocker.get_recorders(), [obj2]) def test_mock(self): mock = self.mocker.mock() self.assertEquals(mock.__mocker_name__, None) self.assertEquals(mock.__mocker_spec__, None) self.assertEquals(mock.__mocker_type__, None) self.assertEquals(mock.__mocker_count__, True) def test_mock_with_name(self): mock = self.mocker.mock(name="name") self.assertEquals(mock.__mocker_name__, "name") def test_mock_with_spec(self): class C(object): pass mock = self.mocker.mock(spec=C) self.assertEquals(mock.__mocker_spec__, C) def test_mock_with_type(self): class C(object): pass mock = self.mocker.mock(type=C) self.assertEquals(mock.__mocker_type__, C) def test_mock_with_spec_and_type(self): class C(object): pass mock = self.mocker.mock(C) self.assertEquals(mock.__mocker_spec__, C) self.assertEquals(mock.__mocker_type__, C) def test_mock_with_count(self): class C(object): pass mock = self.mocker.mock(count=False) self.assertEquals(mock.__mocker_count__, False) def test_proxy(self): original = object() mock = self.mocker.proxy(original) self.assertEquals(type(mock), Mock) self.assertEquals(mock.__mocker_object__, original) self.assertEquals(mock.__mocker_path__.root_object, original) self.assertEquals(mock.__mocker_count__, True) def test_proxy_with_count(self): original = object() mock = self.mocker.proxy(original, count=False) self.assertEquals(mock.__mocker_count__, False) def test_proxy_with_spec(self): original = object() class C(object): pass mock = self.mocker.proxy(original, C) self.assertEquals(mock.__mocker_object__, original) self.assertEquals(mock.__mocker_spec__, C) def test_proxy_with_type(self): original = object() class C(object): pass mock = self.mocker.proxy(original, type=C) self.assertEquals(mock.__mocker_type__, C) def test_proxy_spec_defaults_to_the_object_itself(self): original = object() mock = self.mocker.proxy(original) self.assertEquals(mock.__mocker_spec__, original) def test_proxy_type_defaults_to_the_object_type(self): original = object() mock = self.mocker.proxy(original) self.assertEquals(mock.__mocker_type__, object) def test_proxy_with_spec_and_type_none(self): original = object() mock = self.mocker.proxy(original, spec=None, type=None) self.assertEquals(mock.__mocker_spec__, None) self.assertEquals(mock.__mocker_type__, None) def test_proxy_with_passthrough_false(self): original = object() class C(object): pass mock = self.mocker.proxy(original, C, passthrough=False) self.assertEquals(mock.__mocker_object__, original) self.assertEquals(mock.__mocker_spec__, C) self.assertEquals(mock.__mocker_passthrough__, False) def test_proxy_with_submodule_string(self): from os import path module = self.mocker.proxy("os.path") self.assertEquals(type(module), Mock) self.assertEquals(type(module.__mocker_object__), ModuleType) self.assertEquals(module.__mocker_name__, "os.path") self.assertEquals(module.__mocker_object__, path) def test_proxy_with_module_function_string(self): mock = self.mocker.proxy("os.path.join.func_name") self.assertEquals(mock.__mocker_object__, "join") def test_proxy_with_string_and_name(self): module = self.mocker.proxy("os.path", name="mock") self.assertEquals(module.__mocker_name__, "mock") def test_proxy_with_unexistent_module(self): self.assertRaises(ImportError, self.mocker.proxy, "unexistent.module") def test_replace(self): obj = object() proxy = self.mocker.replace(obj, spec=object, name="obj", count=False, passthrough=False) self.assertEquals(type(proxy), Mock) self.assertEquals(type(proxy.__mocker_object__), object) self.assertEquals(proxy.__mocker_object__, obj) self.assertEquals(proxy.__mocker_spec__, object) self.assertEquals(proxy.__mocker_name__, "obj") self.assertEquals(proxy.__mocker_count__, False) (event,) = self.mocker.get_events() self.assertEquals(type(event), ReplayRestoreEvent) (task,) = event.get_tasks() self.assertEquals(type(task), ProxyReplacer) self.assertTrue(task.mock is proxy) self.assertTrue(task.mock.__mocker_object__ is obj) self.assertTrue(proxy is not obj) def test_replace_with_submodule_string(self): from os import path module = self.mocker.replace("os.path") self.assertEquals(type(module), Mock) self.assertEquals(type(module.__mocker_object__), ModuleType) self.assertEquals(module.__mocker_name__, "os.path") self.assertEquals(module.__mocker_object__, path) (event,) = self.mocker.get_events() (task,) = event.get_tasks() self.assertEquals(type(task), ProxyReplacer) self.assertTrue(task.mock is module) self.assertTrue(task.mock.__mocker_object__ is path) self.assertTrue(module is not path) def test_replace_with_module_function_string(self): mock = self.mocker.replace("os.path.join.func_name") self.assertEquals(mock.__mocker_object__, "join") def test_replace_with_string_and_name(self): module = self.mocker.replace("os.path", name="mock") self.assertEquals(module.__mocker_name__, "mock") def test_replace_with_type(self): original = object() class C(object): pass mock = self.mocker.replace(original, type=C) self.assertEquals(mock.__mocker_type__, C) def test_replace_spec_defaults_to_the_object_itself(self): original = object() mock = self.mocker.replace(original) self.assertEquals(mock.__mocker_spec__, original) def test_replace_type_defaults_to_the_object_type(self): original = object() mock = self.mocker.replace(original) self.assertEquals(mock.__mocker_type__, object) def test_replace_with_spec_and_type_none(self): original = object() mock = self.mocker.replace(original, spec=None, type=None) self.assertEquals(mock.__mocker_spec__, None) self.assertEquals(mock.__mocker_type__, None) def test_replace_with_passthrough_false(self): original = object() class C(object): pass mock = self.mocker.replace(original, passthrough=False) self.assertEquals(mock.__mocker_passthrough__, False) def test_replace_with_bound_method(self): from Queue import Queue mock = self.mocker.replace(Queue.empty) self.assertEquals(mock.__mocker_object__, Queue.empty.im_func) def test_add_and_get_event(self): self.mocker.add_event(41) self.assertEquals(self.mocker.add_event(42), 42) self.assertEquals(self.mocker.get_events(), [41, 42]) def test_recording(self): obj = self.mocker.mock() obj.attr() self.assertEquals(len(self.recorded), 2) action1 = Action("getattr", ("attr",), {}) action2 = Action("call", (), {}) mocker1, event1 = self.recorded[0] self.assertEquals(mocker1, self.mocker) self.assertEquals(type(event1), Event) self.assertTrue(event1.path.matches(Path(obj, None, [action1]))) mocker2, event2 = self.recorded[1] self.assertEquals(mocker2, self.mocker) self.assertEquals(type(event2), Event) self.assertTrue(event2.path.matches(Path(obj, None, [action1, action2]))) self.assertEquals(self.mocker.get_events(), [event1, event2]) def test_recording_result_path(self): obj = self.mocker.mock() result = obj.attr() path = Path(obj, None, [Action("getattr", ("attr",), {}), Action("call", (), {})]) self.assertTrue(result.__mocker_path__.matches(path)) def test_replaying_no_events(self): self.mocker.replay() try: self.mocker.act(self.path) except AssertionError, e: pass else: self.fail("AssertionError not raised") self.assertEquals(str(e), "[Mocker] Unexpected expression: mock.attr") def test_replaying_matching(self): calls = [] class MyTask(Task): def matches(_, path): calls.append("matches") self.assertTrue(self.path.matches(path)) return True def run(_, path): calls.append("run") self.assertTrue(self.path.matches(path)) return "result" event = Event() event.add_task(MyTask()) self.mocker.add_event(event) self.mocker.replay() self.assertEquals(self.mocker.act(self.path), "result") self.assertEquals(calls, ["matches", "run"]) def test_replaying_none_matching(self): calls = [] class MyTask(Task): def matches(_, path): self.assertTrue(self.path.matches(path)) calls.append("matches") return False event = Event() event.add_task(MyTask()) self.mocker.add_event(event) self.mocker.replay() self.assertRaises(AssertionError, self.mocker.act, self.path) self.assertEquals(calls, ["matches"]) def test_replay_order(self): """ When playing back, the precedence of events is as follows: 1. Events with may_run() true 2. Events with satisfied() false 3. Events with has_run() false """ class MyTaskBase(Task): postpone = 2 def may_run(self, path): if not self.postpone: return True self.postpone -= 1 def run(self, path): return self.__class__.__name__ class MyTask1(MyTaskBase): pass class MyTask2(MyTaskBase): pass class MyTask3(MyTaskBase): raised = False def verify(self): if not self.postpone and not self.raised: self.raised = True raise AssertionError("An error") class MyTask4(MyTaskBase): postpone = 0 class MyTask5(MyTaskBase): postpone = 1 event1 = self.mocker.add_event(Event()) event1.add_task(MyTask1()) event2 = self.mocker.add_event(Event()) event2.add_task(MyTask2()) event3 = self.mocker.add_event(Event()) event3.add_task(MyTask3()) event4 = self.mocker.add_event(Event()) event4.add_task(MyTask4()) event5 = self.mocker.add_event(Event()) event5.add_task(MyTask5()) self.mocker.replay() # Labels: [M]ay run, [S]atisfied, [H]as run # State: 1=S 2=S 3= 4=MS 5=S self.assertEquals(self.mocker.act(self.path), "MyTask4") # State: 1=S 2=S 3= 4=MSH 5=S self.assertEquals(self.mocker.act(self.path), "MyTask4") # State: 1=MS 2=MS 3=M 4=MSH 5=MS self.assertEquals(self.mocker.act(self.path), "MyTask3") # State: 1=MS 2=MS 3=MSH 4=MSH 5=MS self.assertEquals(self.mocker.act(self.path), "MyTask1") # State: 1=MSH 2=MS 3=MSH 4=MSH 5=MS self.assertEquals(self.mocker.act(self.path), "MyTask2") # State: 1=MSH 2=MSH 3=MSH 4=MSH 5=MS self.assertEquals(self.mocker.act(self.path), "MyTask5") # State: 1=MSH 2=MSH 3=MSH 4=MSH 5=MSH self.assertEquals(self.mocker.act(self.path), "MyTask1") def test_recorder_decorator(self): result = recorder(42) try: self.assertEquals(result, 42) self.assertEquals(Mocker.get_recorders()[-1], 42) self.assertEquals(MockerBase.get_recorders(), []) finally: Mocker.remove_recorder(42) def test_result(self): event1 = self.mocker.add_event(Event()) event2 = self.mocker.add_event(Event()) self.mocker.result(123) self.assertEquals(event2.run(self.path), 123) def test_throw(self): class MyException(Exception): pass event1 = self.mocker.add_event(Event()) event2 = self.mocker.add_event(Event()) self.mocker.throw(MyException) self.assertRaises(MyException, event2.run, self.path) def test_call(self): event1 = self.mocker.add_event(Event()) event2 = self.mocker.add_event(Event()) self.mocker.call(lambda *args, **kwargs: 123) self.assertEquals(event2.run(self.path), 123) def test_call_with_object(self): obj = object() mock = self.mocker.proxy(obj) action = Action("getattr", ("attr",), {}, Path(mock, root_object=456)) path = action.path + self.action event1 = self.mocker.add_event(Event(path)) event2 = self.mocker.add_event(Event(path)) self.mocker.call(lambda *args, **kwargs: (args, kwargs), with_object=True) self.assertEquals(event1.get_tasks(), []) (task,) = event2.get_tasks() self.assertEquals(type(task), FunctionRunner) self.assertEquals(event2.run(event2.path), ((456, "attr"), {})) def test_call_with_object_needs_proxy(self): obj = object() mock = self.mocker.proxy(obj) action = Action("getattr", ("attr",), {}, Path(mock, root_object=456)) path = action.path + self.action event1 = self.mocker.add_event(Event(path)) event2 = self.mocker.add_event(Event(path)) self.mocker.call(lambda *args, **kwargs: (args, kwargs), with_object=True) self.assertEquals(event1.get_tasks(), []) (task,) = event2.get_tasks() self.assertEquals(type(task), FunctionRunner) self.assertEquals(event2.run(event2.path), ((456, "attr"), {})) def test_call_with_object_fails_on_unproxied(self): mock = self.mocker.mock() event1 = self.mocker.add_event(Event(Path(mock))) event2 = self.mocker.add_event(Event(Path(mock))) self.assertRaises(TypeError, self.mocker.call, lambda *args: None, with_object=True) def test_count(self): class MyTask(Task): pass event1 = self.mocker.add_event(Event()) event2 = self.mocker.add_event(Event()) event2.add_task(MyTask()) event2.add_task(ImplicitRunCounter(1)) event2.add_task(ImplicitRunCounter(1)) self.mocker.count(2, 3) self.assertEquals(len(event1.get_tasks()), 0) (task1, task2,) = event2.get_tasks() self.assertEquals(type(task1), RunCounter) self.assertEquals(type(task2), MyTask) self.assertEquals(task1.min, 2) self.assertEquals(task1.max, 3) self.mocker.count(4) self.assertEquals(len(event1.get_tasks()), 0) (task1, task2) = event2.get_tasks() self.assertEquals(type(task1), RunCounter) self.assertEquals(type(task2), MyTask) self.assertEquals(task1.min, 4) self.assertEquals(task1.max, 4) def test_count_without_implicit_counter(self): class MyTask(Task): pass event1 = self.mocker.add_event(Event()) event2 = self.mocker.add_event(Event()) event2.add_task(MyTask()) self.mocker.count(2, 3) self.assertEquals(len(event1.get_tasks()), 0) (task1, task2,) = event2.get_tasks() self.assertEquals(type(task1), RunCounter) self.assertEquals(type(task2), MyTask) self.assertEquals(task1.min, 2) self.assertEquals(task1.max, 3) def test_order(self): mock1 = self.mocker.mock() mock2 = self.mocker.mock() mock3 = self.mocker.mock() mock4 = self.mocker.mock() result1 = mock1.attr1(1) result2 = mock2.attr2(2) result3 = mock3.attr3(3) result4 = mock4.attr4(4) # Try to spoil the logic which decides which task to reuse. other_task = Task() for event in self.mocker.get_events(): event.add_task(other_task) self.mocker.order(result1, result2, result3) self.mocker.order(result1, result4) self.mocker.order(result2, result4) events = self.mocker.get_events() self.assertEquals(len(events), 8) self.assertEquals(events[0].get_tasks(), [other_task]) other_task_, task1 = events[1].get_tasks() self.assertEquals(type(task1), Orderer) self.assertEquals(task1.path, events[1].path) self.assertEquals(task1.get_dependencies(), []) self.assertEquals(other_task_, other_task) self.assertEquals(events[2].get_tasks(), [other_task]) other_task_, task3 = events[3].get_tasks() self.assertEquals(type(task3), Orderer) self.assertEquals(task3.path, events[3].path) self.assertEquals(task3.get_dependencies(), [task1]) self.assertEquals(other_task_, other_task) self.assertEquals(events[4].get_tasks(), [other_task]) other_task_, task5 = events[5].get_tasks() self.assertEquals(type(task5), Orderer) self.assertEquals(task5.path, events[5].path) self.assertEquals(task5.get_dependencies(), [task3]) self.assertEquals(other_task_, other_task) self.assertEquals(events[6].get_tasks(), [other_task]) other_task_, task7 = events[7].get_tasks() self.assertEquals(type(task7), Orderer) self.assertEquals(task7.path, events[7].path) self.assertEquals(task7.get_dependencies(), [task1, task3]) self.assertEquals(other_task_, other_task) def test_after(self): mock1 = self.mocker.mock() mock2 = self.mocker.mock() mock3 = self.mocker.mock() result1 = mock1.attr1(1) result2 = mock2.attr2(2) result3 = mock3.attr3(3) # Try to spoil the logic which decides which task to reuse. other_task = Task() for event in self.mocker.get_events(): event.add_task(other_task) self.mocker.after(result1, result2) events = self.mocker.get_events() self.assertEquals(len(events), 6) self.assertEquals(events[0].get_tasks(), [other_task]) other_task_, task1 = events[1].get_tasks() self.assertEquals(type(task1), Orderer) self.assertEquals(task1.path, events[1].path) self.assertEquals(task1.get_dependencies(), []) self.assertEquals(other_task_, other_task) self.assertEquals(events[2].get_tasks(), [other_task]) other_task_, task3 = events[3].get_tasks() self.assertEquals(type(task3), Orderer) self.assertEquals(task3.path, events[3].path) self.assertEquals(task3.get_dependencies(), []) self.assertEquals(other_task_, other_task) self.assertEquals(events[4].get_tasks(), [other_task]) other_task_, task5 = events[5].get_tasks() self.assertEquals(type(task5), Orderer) self.assertEquals(task5.path, events[5].path) self.assertEquals(task5.get_dependencies(), [task1, task3]) self.assertEquals(other_task_, other_task) def test_before(self): mock1 = self.mocker.mock() mock2 = self.mocker.mock() mock3 = self.mocker.mock() result1 = mock1.attr1(1) result2 = mock2.attr2(2) result3 = mock3.attr3(3) # Try to spoil the logic which decides which task to reuse. other_task = Task() for event in self.mocker.get_events(): event.add_task(other_task) self.mocker.before(result1, result2) events = self.mocker.get_events() self.assertEquals(len(events), 6) self.assertEquals(events[4].get_tasks(), [other_task]) other_task_, task5 = events[5].get_tasks() self.assertEquals(type(task5), Orderer) self.assertEquals(task5.path, events[5].path) self.assertEquals(task5.get_dependencies(), []) self.assertEquals(other_task_, other_task) self.assertEquals(events[0].get_tasks(), [other_task]) other_task_, task1 = events[1].get_tasks() self.assertEquals(type(task1), Orderer) self.assertEquals(task1.path, events[1].path) self.assertEquals(task1.get_dependencies(), [task5]) self.assertEquals(other_task_, other_task) self.assertEquals(events[2].get_tasks(), [other_task]) other_task_, task3 = events[3].get_tasks() self.assertEquals(type(task3), Orderer) self.assertEquals(task3.path, events[3].path) self.assertEquals(task3.get_dependencies(), [task5]) self.assertEquals(other_task_, other_task) def test_default_ordering(self): self.assertEquals(self.mocker.is_ordering(), False) def test_order_without_arguments(self): self.mocker.order() self.assertEquals(self.mocker.is_ordering(), True) def test_order_with_context_manager(self): with_manager = self.mocker.order() self.assertEquals(self.mocker.is_ordering(), True) with_manager.__enter__() self.assertEquals(self.mocker.is_ordering(), True) with_manager.__exit__(None, None, None) self.assertEquals(self.mocker.is_ordering(), False) def test_unorder(self): self.mocker.order() self.mocker.unorder() self.assertEquals(self.mocker.is_ordering(), False) def test_ordered_events(self): mock = self.mocker.mock() # Ensure that the state is correctly reset between # different ordered blocks. self.mocker.order() mock.a self.mocker.unorder() self.mocker.order() mock.x.y.z events = self.mocker.get_events() (task1,) = events[1].get_tasks() (task2,) = events[2].get_tasks() (task3,) = events[3].get_tasks() self.assertEquals(type(task1), Orderer) self.assertEquals(type(task2), Orderer) self.assertEquals(type(task3), Orderer) self.assertEquals(task1.path, events[1].path) self.assertEquals(task2.path, events[2].path) self.assertEquals(task3.path, events[3].path) self.assertEquals(task1.get_dependencies(), []) self.assertEquals(task2.get_dependencies(), [task1]) self.assertEquals(task3.get_dependencies(), [task2]) def test_nospec(self): event1 = self.mocker.add_event(Event()) event2 = self.mocker.add_event(Event()) task1 = event1.add_task(SpecChecker(None)) task2 = event2.add_task(Task()) task3 = event2.add_task(SpecChecker(None)) task4 = event2.add_task(Task()) self.mocker.nospec() self.assertEquals(event1.get_tasks(), [task1]) self.assertEquals(event2.get_tasks(), [task2, task4]) def test_passthrough(self): obj = object() mock = self.mocker.proxy(obj) event1 = self.mocker.add_event(Event(Path(mock, obj))) event2 = self.mocker.add_event(Event(Path(mock, obj))) self.mocker.passthrough() self.assertEquals(event1.get_tasks(), []) (task,) = event2.get_tasks() self.assertEquals(type(task), PathExecuter) def test_passthrough_fails_on_unproxied(self): mock = self.mocker.mock() event1 = self.mocker.add_event(Event(Path(mock))) event2 = self.mocker.add_event(Event(Path(mock))) self.assertRaises(TypeError, self.mocker.passthrough) def test_passthrough_with_result_callback(self): obj = object() mock = self.mocker.proxy(obj) event = self.mocker.add_event(Event(Path(mock, obj))) result_callback = object() self.mocker.passthrough(result_callback) (task,) = event.get_tasks() self.assertEquals(task.get_result_callback(), result_callback) def test_on(self): obj = self.mocker.mock() self.mocker.on(obj.attr).result(123) self.mocker.replay() self.assertEquals(obj.attr, 123) def test_patch(self): class C(object): pass mock = self.mocker.patch(C) self.assertEquals(type(C.__mocker_mock__), Mock) self.assertTrue(C.__mocker_mock__ is mock) self.assertTrue(mock.__mocker_object__ is C) self.assertEquals(type(mock.__mocker_patcher__), Patcher) self.assertEquals(mock.__mocker_passthrough__, True) self.assertEquals(mock.__mocker_spec__, C) (event,) = self.mocker.get_events() self.assertEquals(type(event), ReplayRestoreEvent) (task,) = event.get_tasks() self.assertTrue(task is mock.__mocker_patcher__) def test_patch_without_spec(self): class C(object): pass mock = self.mocker.patch(C, spec=None) self.assertEquals(mock.__mocker_spec__, None) def test_patch_and_restore_unsets_mocker_mock(self): class C(object): pass mock = self.mocker.patch(C) self.mocker.replay() self.assertTrue("__mocker_mock__" in C.__dict__) self.mocker.restore() self.assertFalse("__mocker_mock__" in C.__dict__) class ActionTest(TestCase): def setUp(self): self.mock = Mock(None, name="mock") def test_create(self): objects = [object() for i in range(4)] action = Action(*objects) self.assertEquals(action.kind, objects[0]) self.assertEquals(action.args, objects[1]) self.assertEquals(action.kwargs, objects[2]) self.assertEquals(action.path, objects[3]) def test_repr(self): self.assertEquals(repr(Action("kind", "args", "kwargs")), "Action('kind', 'args', 'kwargs')") self.assertEquals(repr(Action("kind", "args", "kwargs", "path")), "Action('kind', 'args', 'kwargs', 'path')") def test_execute_unknown(self): self.assertRaises(RuntimeError, Action("unknown", (), {}).execute, None) def test_execute_getattr(self): class C(object): pass obj = C() obj.attr = C() action = Action("getattr", ("attr",), {}) self.assertEquals(action.execute(obj), obj.attr) def test_execute_setattr(self): class C(object): pass obj = C() action = Action("setattr", ("attr", "value"), {}) action.execute(obj) self.assertEquals(getattr(obj, "attr", None), "value") def test_execute_delattr(self): class C(object): pass obj = C() obj.attr = "value" action = Action("delattr", ("attr",), {}) action.execute(obj) self.assertEquals(getattr(obj, "attr", None), None) def test_execute_call(self): obj = lambda a, b: a+b action = Action("call", (1,), {"b": 2}) self.assertEquals(action.execute(obj), 3) def test_execute_contains(self): obj = ["a"] action = Action("contains", ("a",), {}) self.assertEquals(action.execute(obj), True) action = Action("contains", ("b",), {}) self.assertEquals(action.execute(obj), False) def test_execute_getitem(self): obj = {"a": 1} action = Action("getitem", ("a",), {}) self.assertEquals(action.execute(obj), 1) action = Action("getitem", ("b",), {}) self.assertRaises(KeyError, action.execute, obj) def test_execute_setitem(self): obj = {} action = Action("setitem", ("a", 1), {}) action.execute(obj) self.assertEquals(obj, {"a": 1}) def test_execute_delitem(self): obj = {"a": 1, "b": 2} action = Action("delitem", ("a",), {}) action.execute(obj) self.assertEquals(obj, {"b": 2}) def test_execute_len(self): obj = [1, 2, 3] action = Action("len", (), {}) self.assertEquals(action.execute(obj), 3) def test_execute_nonzero(self): obj = [] action = Action("nonzero", (), {}) self.assertEquals(action.execute(obj), False) obj = [1] action = Action("nonzero", (), {}) self.assertEquals(action.execute(obj), True) def test_execute_iter(self): obj = [1, 2, 3] action = Action("iter", (), {}) result = action.execute(obj) self.assertEquals(type(result), type(iter(obj))) self.assertEquals(list(result), obj) def test_execute_caching(self): values = iter(range(10)) obj = lambda: values.next() action = Action("call", (), {}) self.assertEquals(action.execute(obj), 0) self.assertEquals(action.execute(obj), 0) obj = lambda: values.next() self.assertEquals(action.execute(obj), 1) def test_equals(self): obj1 = object() obj2 = object() self.assertEquals(Action("kind", (), {}, obj1), Action("kind", (), {}, obj2)) self.assertNotEquals(Action("kind", (), {}, obj1), Action("dnik", (), {}, obj2)) self.assertNotEquals(Action("kind", (), {}, obj1), Action("kind", (1,), {}, obj2)) self.assertNotEquals(Action("kind", (), {}, obj1), Action("kind", (), {"a": 1}, obj2)) self.assertNotEquals(Action("kind", (ANY,), {}, obj1), Action("kind", (1,), {}, obj2)) self.assertEquals(Action("kind", (CONTAINS(1),), {}, obj1), Action("kind", (CONTAINS(1),), {}, obj2)) def test_matches(self): obj1 = object() obj2 = object() action1 = Action("kind", (), {}, obj1) action2 = Action("kind", (), {}, obj2) self.assertTrue(action1.matches(action2)) action1 = Action("kind", (), {}, obj1) action2 = Action("dnik", (), {}, obj2) self.assertFalse(action1.matches(action2)) action1 = Action("kind", (), {}, obj1) action2 = Action("kind", (1,), {}, obj2) self.assertFalse(action1.matches(action2)) action1 = Action("kind", (), {}, obj1) action2 = Action("kind", (), {"a": 1}, obj2) self.assertFalse(action1.matches(action2)) action1 = Action("kind", (ARGS,), {}, obj1) action2 = Action("kind", (), {}, obj2) self.assertTrue(action1.matches(action2)) action1 = Action("kind", (ARGS,), {"a": 1}, obj1) action2 = Action("kind", (), {}, obj2) self.assertFalse(action1.matches(action2)) class PathTest(TestCase): def setUp(self): class StubMocker(object): def act(self, path): pass self.mocker = StubMocker() self.mock = Mock(self.mocker, name="obj") self.object = object() def test_create(self): mock = object() path = Path(mock) self.assertEquals(path.root_mock, mock) self.assertEquals(path.root_object, None) self.assertEquals(path.actions, ()) def test_create_with_object(self): mock = object() path = Path(mock, self.object) self.assertEquals(path.root_mock, mock) self.assertEquals(path.root_object, self.object) def test_create_with_actions(self): mock = object() path = Path(mock, self.object, [1,2,3]) self.assertEquals(path.root_mock, mock) self.assertEquals(path.root_object, self.object) self.assertEquals(path.actions, (1,2,3)) def test_add(self): mock = object() path = Path(mock, self.object, [1,2,3]) result = path + 4 self.assertTrue(result is not path) self.assertEquals(result.root_mock, mock) self.assertEquals(result.root_object, self.object) self.assertEquals(result.actions, (1,2,3,4)) def test_parent_path(self): path1 = Path(self.mock) path2 = path1 + Action("getattr", ("attr",), {}, path1) path3 = path2 + Action("getattr", ("attr",), {}, path2) self.assertEquals(path1.parent_path, None) self.assertEquals(path2.parent_path, path1) self.assertEquals(path3.parent_path, path2) def test_equals(self): mock = object() obj = object() obj1 = object() obj2 = object() # Not the *same* mock. path1 = Path([], obj, []) path2 = Path([], obj, []) self.assertNotEquals(path1, path2) # Not the *same* object. path1 = Path(mock, [], []) path2 = Path(mock, [], []) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (), {}, obj2)]) self.assertEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("dnik", (), {}, obj2)]) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(object(), obj, [Action("kind", (), {}, obj2)]) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (1,), {}, obj2)]) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (), {"a": 1}, obj2)]) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, []) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (ANY,), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (1,), {}, obj2)]) self.assertNotEquals(path1, path2) path1 = Path(mock, obj, [Action("kind", (CONTAINS(1),), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (CONTAINS(1),), {}, obj2)]) self.assertEquals(path1, path2) def test_matches(self): obj = object() mock = object() obj1 = object() obj2 = object() # Not the *same* mock. path1 = Path([], obj, []) path2 = Path([], obj, []) self.assertFalse(path1.matches(path2)) path1 = Path(mock, obj1, []) path2 = Path(mock, obj2, []) self.assertTrue(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (), {}, obj2)]) self.assertTrue(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("dnik", (), {}, obj2)]) self.assertFalse(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(object(), [Action("kind", (), {}, obj2)]) self.assertFalse(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (1,), {}, obj2)]) self.assertFalse(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (), {"a": 1}, obj2)]) self.assertFalse(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (), {}, obj1)]) path2 = Path(mock, obj, []) self.assertFalse(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (ARGS,), {}, obj1)]) path2 = Path(mock, obj, [Action("kind", (), {}, obj2)]) self.assertTrue(path1.matches(path2)) path1 = Path(mock, obj, [Action("kind", (ARGS,), {"a": 1}, obj1)]) path2 = Path(mock, obj, [Action("kind", (), {}, obj2)]) self.assertFalse(path1.matches(path2)) def test_str(self): path = Path(self.mock, []) self.assertEquals(str(path), "obj") def test_str_unnamed(self): mock = Mock(self.mocker) path = Path(mock, []) self.assertEquals(str(path), "") def test_str_auto_named(self): named_mock = Mock(self.mocker) named_mock.attr path = Path(named_mock, []) self.assertEquals(str(path), "named_mock") def test_str_getattr(self): path = Path(self.mock, None, [Action("getattr", ("attr",), {})]) self.assertEquals(str(path), "obj.attr") path += Action("getattr", ("x",), {}) self.assertEquals(str(path), "obj.attr.x") def test_str_getattr_call(self): path = Path(self.mock, None, [Action("getattr", ("x",), {}), Action("getattr", ("y",), {}), Action("call", ("z",), {})]) self.assertEquals(str(path), "obj.x.y('z')") def test_str_setattr(self): path = Path(self.mock, None, [Action("setattr", ("attr", "value"), {})]) self.assertEquals(str(path), "obj.attr = 'value'") def test_str_delattr(self): path = Path(self.mock, None, [Action("delattr", ("attr",), {})]) self.assertEquals(str(path), "del obj.attr") def test_str_call(self): path = Path(self.mock, None, [Action("call", (), {})]) self.assertEquals(str(path), "obj()") path = Path(self.mock, None, [Action("call", (1, "2"), {"a": 3, "b": "4"})]) self.assertEquals(str(path), "obj(1, '2', a=3, b='4')") def test_str_contains(self): path = Path(self.mock, None, [Action("contains", ("value",), {})]) self.assertEquals(str(path), "'value' in obj") def test_str_getitem(self): path = Path(self.mock, None, [Action("getitem", ("key",), {})]) self.assertEquals(str(path), "obj['key']") def test_str_setitem(self): path = Path(self.mock, None, [Action("setitem", ("key", "value"), {})]) self.assertEquals(str(path), "obj['key'] = 'value'") def test_str_delitem(self): path = Path(self.mock, None, [Action("delitem", ("key",), {})]) self.assertEquals(str(path), "del obj['key']") def test_str_len(self): path = Path(self.mock, None, [Action("len", (), {})]) self.assertEquals(str(path), "len(obj)") def test_str_nonzero(self): path = Path(self.mock, None, [Action("nonzero", (), {})]) self.assertEquals(str(path), "bool(obj)") def test_str_iter(self): path = Path(self.mock, None, [Action("iter", (), {})]) self.assertEquals(str(path), "iter(obj)") def test_str_raises_on_unknown(self): path = Path(self.mock, None, [Action("unknown", (), {})]) self.assertRaises(RuntimeError, str, path) def test_execute(self): class C(object): pass obj = C() obj.x = C() obj.x.y = lambda a, b: a+b path = Path(self.mock, None, [Action("getattr", ("x",), {}), Action("getattr", ("y",), {}), Action("call", (1,), {"b": 2})]) self.assertEquals(path.execute(obj), 3) class MatchParamsTest(TestCase): def true(self, *args): self.assertTrue(match_params(*args), repr(args)) def false(self, *args): self.assertFalse(match_params(*args), repr(args)) def test_any_repr(self): self.assertEquals(repr(ANY), "ANY") def test_any_equals(self): self.assertEquals(ANY, ANY) self.assertNotEquals(ANY, ARGS) self.assertNotEquals(ANY, object()) def test_any_matches(self): self.assertTrue(ANY.matches(1)) self.assertTrue(ANY.matches(42)) self.assertTrue(ANY.matches(object())) def test_is_repr(self): self.assertEquals(repr(IS("obj")), "IS('obj')") def test_is_equals(self): l1 = [] l2 = [] self.assertNotEquals(IS(l1), l2) self.assertEquals(IS(l1), IS(l1)) self.assertNotEquals(IS(l1), IS(l2)) def test_is_matches(self): l1 = [] l2 = [] self.assertTrue(IS(l1).matches(l1)) self.assertFalse(IS(l1).matches(l2)) self.assertFalse(IS(l1).matches(ANY)) def test_contains_repr(self): self.assertEquals(repr(CONTAINS("obj")), "CONTAINS('obj')") def test_contains_equals(self): self.assertEquals(CONTAINS([1]), CONTAINS([1])) self.assertNotEquals(CONTAINS(1), CONTAINS([1])) def test_contains_matches(self): self.assertTrue(CONTAINS(1).matches([1])) self.assertFalse(CONTAINS([1]).matches([1])) self.assertFalse(CONTAINS(1).matches(object())) def test_contains_matches_with_contains(self): """Can't be iterated, but has contains hook.""" class C(object): def __contains__(self, value): return True self.assertTrue(CONTAINS(1).matches(C())) def test_in_repr(self): self.assertEquals(repr(IN("obj")), "IN('obj')") def test_in_equals(self): self.assertEquals(IN([1]), IN([1])) self.assertNotEquals(IN([1]), IN(1)) def test_in_matches(self): self.assertTrue(IN([1]).matches(1)) self.assertFalse(IN([1]).matches([1])) self.assertFalse(IN([1]).matches(object())) def test_match_repr(self): self.assertEquals(repr(MATCH("obj")), "MATCH('obj')") def test_match_equals(self): obj1, obj2 = [], [] self.assertEquals(MATCH(obj1), MATCH(obj1)) self.assertNotEquals(MATCH(obj1), MATCH(obj2)) def test_match_matches(self): self.assertTrue(MATCH(lambda x: x > 10).matches(15)) self.assertFalse(MATCH(lambda x: x > 10).matches(5)) def test_normal(self): self.true((), {}, (), {}) self.true((1, 2), {"a": 3}, (1, 2), {"a": 3}) self.false((1,), {}, (), {}) self.false((), {}, (1,), {}) self.false((1, 2), {"a": 3}, (1, 2), {"a": 4}) self.false((1, 2), {"a": 3}, (1, 3), {"a": 3}) def test_any(self): self.true((1, 2), {"a": ANY}, (1, 2), {"a": 4}) self.true((1, ANY), {"a": 3}, (1, 3), {"a": 3}) self.false((ANY,), {}, (), {}) def test_special_args_matching(self): self.true((1, IN([2])), {}, (1, 2), {}) self.true((1, 2), {"a": IN([3])}, (1, 2), {"a": 3}) self.false((1, IN([2])), {}, (1, 3), {}) self.false((1, 2), {"a": IN([3])}, (1, 2), {"a": 4}) def test_args_alone(self): self.true((ARGS,), {}, (), {}) self.true((ARGS,), {}, (1, 2), {}) self.false((ARGS,), {}, (1, 2), {"a": 2}) self.false((ARGS,), {}, (), {"a": 2}) self.true((ARGS,), {"a": 1}, (), {"a": 1}) self.true((ARGS,), {"a": 1}, (1, 2), {"a": 1}) self.false((ARGS,), {"a": 1}, (), {"a": 1, "b": 2}) self.false((ARGS,), {"a": 1}, (1, 2), {"a": 1, "b": 2}) self.false((ARGS,), {"a": 1}, (), {}) def test_kwargs_alone(self): self.true((KWARGS,), {}, (), {}) self.false((KWARGS,), {}, (1, 2), {}) self.false((KWARGS,), {}, (1, 2), {"a": 2}) self.true((KWARGS,), {}, (), {"a": 2}) self.true((KWARGS,), {"a": 1}, (), {"a": 1}) self.false((KWARGS,), {"a": 1}, (1, 2), {"a": 1}) self.true((KWARGS,), {"a": 1}, (), {"a": 1, "b": 2}) self.false((KWARGS,), {"a": 1}, (1, 2), {"a": 1, "b": 2}) self.false((KWARGS,), {"a": 1}, (), {}) def test_args_kwargs(self): self.true((ARGS, KWARGS), {}, (), {}) self.true((ARGS, KWARGS), {}, (1, 2), {}) self.true((ARGS, KWARGS), {}, (1, 2), {"a": 2}) self.true((ARGS, KWARGS), {}, (), {"a": 2}) self.true((ARGS, KWARGS), {"a": 1}, (), {"a": 1}) self.true((ARGS, KWARGS), {"a": 1}, (1, 2), {"a": 1}) self.true((ARGS, KWARGS), {"a": 1}, (), {"a": 1, "b": 2}) self.true((ARGS, KWARGS), {"a": 1}, (1, 2), {"a": 1, "b": 2}) self.false((ARGS, KWARGS), {"a": 1}, (), {}) def test_args_at_start(self): self.true((ARGS, 3, 4), {}, (3, 4), {}) self.true((ARGS, 3, 4), {}, (1, 2, 3, 4), {}) self.true((ARGS, 3, 4), {"a": 1}, (3, 4), {"a": 1}) self.false((ARGS, 3, 4), {"a": 1}, (1, 2, 3, 4), {"a": 1, "b": 2}) self.false((ARGS, 3, 4), {}, (), {}) self.false((ARGS, 3, 4), {}, (3, 5), {}) self.false((ARGS, 3, 4), {}, (5, 5), {}) self.false((ARGS, 3, 4), {}, (3, 4, 5), {}) self.false((ARGS, 3, 4), {"a": 1}, (), {}) self.false((ARGS, 3, 4), {"a": 1}, (3, 4), {}) self.false((ARGS, 3, 4), {"a": 1}, (3, 4), {"b": 2}) def test_args_at_end(self): self.true((1, 2, ARGS), {}, (1, 2), {}) self.true((1, 2, ARGS), {}, (1, 2, 3, 4), {}) self.true((1, 2, ARGS), {"a": 1}, (1, 2), {"a": 1}) self.false((1, 2, ARGS), {"a": 1}, (1, 2, 3, 4), {"a": 1, "b": 2}) self.false((1, 2, ARGS), {}, (), {}) self.false((1, 2, ARGS), {}, (1, 3), {}) self.false((1, 2, ARGS), {}, (3, 3), {}) self.false((1, 2, ARGS), {"a": 1}, (), {}) self.false((1, 2, ARGS), {"a": 1}, (1, 2), {}) self.false((1, 2, ARGS), {"a": 1}, (1, 2), {"b": 2}) def test_args_at_middle(self): self.true((1, ARGS, 4), {}, (1, 4), {}) self.true((1, ARGS, 4), {}, (1, 2, 3, 4), {}) self.true((1, ARGS, 4), {"a": 1}, (1, 4), {"a": 1}) self.false((1, ARGS, 4), {"a": 1}, (1, 2, 3, 4), {"a": 1, "b": 2}) self.false((1, ARGS, 4), {}, (), {}) self.false((1, ARGS, 4), {}, (1, 5), {}) self.false((1, ARGS, 4), {}, (5, 5), {}) self.false((1, ARGS, 4), {"a": 1}, (), {}) self.false((1, ARGS, 4), {"a": 1}, (1, 4), {}) self.false((1, ARGS, 4), {"a": 1}, (1, 4), {"b": 2}) def test_args_multiple(self): self.true((ARGS, 3, ARGS, 6, ARGS), {}, (1, 2, 3, 4, 5, 6), {}) self.true((ARGS, ARGS, ARGS), {}, (1, 2, 3, 4, 5, 6), {}) self.true((ARGS, ARGS, ARGS), {}, (), {}) self.false((ARGS, 3, ARGS, 6, ARGS), {}, (1, 2, 3, 4, 5), {}) self.false((ARGS, 3, ARGS, 6, ARGS), {}, (1, 2, 4, 5, 6), {}) class MockTest(TestCase): def setUp(self): self.paths = [] class StubMocker(object): _recording = True def is_recording(self): return self._recording def replay(self): self._recording = False def act(_, path): self.paths.append(path) return 42 self.StubMocker = StubMocker self.mocker = StubMocker() self.mock = Mock(self.mocker) def test_default_attributes(self): self.assertEquals(self.mock.__mocker__, self.mocker) self.assertEquals(self.mock.__mocker_path__, Path(self.mock)) self.assertEquals(self.mock.__mocker_name__, None) self.assertEquals(self.mock.__mocker_spec__, None) self.assertEquals(self.mock.__mocker_type__, None) self.assertEquals(self.mock.__mocker_object__, None) self.assertEquals(self.mock.__mocker_passthrough__, False) self.assertEquals(self.mock.__mocker_patcher__, None) self.assertEquals(self.mock.__mocker_replace__, False) self.assertEquals(self.mock.__mocker_count__, True) def test_path(self): path = object() self.assertEquals(Mock(self.mocker, path).__mocker_path__, path) def test_object(self): mock = Mock(self.mocker, object="foo") self.assertEquals(mock.__mocker_object__, "foo") self.assertEquals(mock.__mocker_path__.root_object, "foo") def test_passthrough(self): mock = Mock(self.mocker, object="foo", passthrough=True) self.assertEquals(mock.__mocker_object__, "foo") self.assertEquals(mock.__mocker_passthrough__, True) def test_spec(self): C = object() self.assertEquals(Mock(self.mocker, spec=C).__mocker_spec__, C) def test_class_without_type(self): mock = Mock(self.mocker) self.assertEquals(mock.__class__, Mock) self.mocker.replay() self.assertEquals(mock.__class__, Mock) def test_class_with_type_when_recording(self): class C(object): pass mock = Mock(self.mocker, type=C) self.assertEquals(mock.__mocker_type__, C) self.assertEquals(mock.__class__, Mock) self.assertEquals(isinstance(mock, Mock), True) def test_class_with_type_when_replaying(self): class C(object): pass mock = Mock(self.mocker, type=C) self.mocker.replay() self.assertEquals(mock.__mocker_type__, C) self.assertEquals(mock.__class__, C) self.assertEquals(isinstance(mock, C), True) def test_auto_naming(self): named_mock = self.mock named_mock.attr another_name = named_mock named_mock = None # Can't find this one anymore. another_name.attr self.assertEquals(another_name.__mocker_name__, "named_mock") def test_auto_naming_on_self(self): self.named_mock = self.mock del self.mock self.named_mock.attr self.assertEquals(self.named_mock.__mocker_name__, "named_mock") def test_auto_naming_on_bad_self(self): self_ = self self = object() # No __dict__ self_.named_mock = self_.mock self_.named_mock.attr self_.assertEquals(self_.named_mock.__mocker_name__, None) def test_auto_naming_without_getframe(self): getframe = sys._getframe sys._getframe = None try: self.named_mock = self.mock self.named_mock.attr self.assertEquals(self.named_mock.__mocker_name__, None) finally: sys._getframe = getframe def test_getattr(self): self.assertEquals(self.mock.attr, 42) (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("getattr", ("attr",), {})) def test_setattr(self): self.mock.attr = 24 (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("setattr", ("attr", 24), {})) def test_delattr(self): del self.mock.attr (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("delattr", ("attr",), {})) def test_call(self): self.mock(1, a=2) (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("call", (1,), {"a": 2})) def test_contains(self): self.assertEquals("value" in self.mock, True) # True due to 42. (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("contains", ("value",), {})) def test_getitem(self): self.assertEquals(self.mock["key"], 42) (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("getitem", ("key",), {})) def test_setitem(self): self.mock["key"] = "value" (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("setitem", ("key", "value"), {})) def test_delitem(self): del self.mock["key"] (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("delitem", ("key",), {})) def test_len(self): self.assertEquals(len(self.mock), 42) (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("len", (), {})) def test_len_with_mock_result(self): self.mocker.act = lambda path: Mock(self.mocker) self.assertEquals(len(self.mock), 0) def test_len_transforms_match_error_to_attribute_error(self): """ list() uses len() as a hint. When we mock iter(), it shouldn't explode due to the lack of len(). """ def raise_error(path): raise MatchError("Kaboom!") self.mocker.act = raise_error try: len(self.mock) except AttributeError, e: self.assertEquals(str(e), "Kaboom!") except MatchError: self.fail("Expected AttributeError, not MatchError.") else: self.fail("AttributeError not raised.") def test_mock_raises_attribute_error_on_length_hint(self): """ In Python 2.6+ list() uses __length_hint__() as a hint. When we mock iter(), it shouldn't explode due to the lack of __length_hint__. """ def raise_error(path): raise MatchError("Kaboom!") self.mocker.act = raise_error try: self.mock.__length_hint__ except AttributeError, e: self.assertEquals(str(e), "No __length_hint__ here!") except MatchError: self.fail("Expected AttributeError, not MatchError.") else: self.fail("AttributeError not raised.") def test_nonzero(self): self.assertEquals(bool(self.mock), True) # True due to 42. (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("nonzero", (), {})) def test_nonzero_returns_true_on_match_error(self): """ When an object doesn't define a boolean behavior explicitly, it should be handled as a true value by default, as Python usually does. """ def raise_error(path): raise MatchError("Kaboom!") self.mocker.act = raise_error self.assertEquals(bool(self.mock), True) def test_nonzero_with_mock_result(self): self.mocker.act = lambda path: Mock(self.mocker) self.assertEquals(bool(self.mock), True) def test_iter(self): result_mock = Mock(self.mocker) self.mocker.act = lambda path: self.paths.append(path) or result_mock result = iter(self.mock) self.assertEquals(type(result), type(iter([]))) self.assertEquals(list(result), []) (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertEquals(path, self.mock.__mocker_path__ + Action("iter", (), {})) def test_passthrough_on_unexpected(self): class StubMocker(object): def act(self, path): if path.actions[-1].args == ("x",): raise MatchError return 42 class C(object): x = 123 y = 321 mock = Mock(StubMocker(), object=C()) self.assertRaises(MatchError, getattr, mock, "x", 42) self.assertEquals(mock.y, 42) mock = Mock(StubMocker(), passthrough=True) self.assertRaises(MatchError, getattr, mock, "x", 42) self.assertEquals(mock.y, 42) mock = Mock(StubMocker(), object=C(), passthrough=True) self.assertEquals(mock.x, 123) self.assertEquals(mock.y, 42) mock = Mock(StubMocker(), passthrough=True) act = mock.__mocker_act__ self.assertEquals(act("getattr", ("x",), 42, object=C()), 123) self.assertEquals(act("getattr", ("y",), 42, object=C()), 42) def test_act_with_object(self): obj = object() self.mock.__mocker_act__("kind", object=obj) (path,) = self.paths self.assertEquals(type(path), Path) self.assertTrue(path.parent_path is self.mock.__mocker_path__) self.assertTrue(path.root_object is obj) def test_reraise_assertion(self): class StubMocker(object): def act(self, path): message = os.linesep.join(["An", "- error", "- happened"]) raise AssertionError(message) mock = Mock(StubMocker()) try: mock.__mocker_act__("kind") except AssertionError, e: message = os.linesep.join(["[Mocker] Unmet expectation:", "", "=> An", " - error", " - happened", ""]) self.assertEquals(str(e), message) else: self.fail("AssertionError not raised") def test_action_execute_and_path_str(self): """Check for kind support on Action.execute() and Path.__str__().""" mocker = Mocker() check = [] for name, attr in Mock.__dict__.iteritems(): if not name.startswith("__mocker_") and hasattr(attr, "__call__"): mock = mocker.mock() args = ["arg"] * (attr.func_code.co_argcount - 1) try: attr(mock, *args) except: pass else: path = mocker.get_events()[-1].path check.append((path, path.actions[-1])) for path, action in check: kind = action.kind try: str(path) except RuntimeError: self.fail("Kind %r not supported by Path.__str__()" % kind) try: action.execute(object()) except RuntimeError: self.fail("Kind %r not supported by Action.execute()" % kind) except: pass class EventTest(TestCase): def setUp(self): self.event = Event() def test_default_path(self): self.assertEquals(self.event.path, None) def test_path(self): path = object() event = Event(path) self.assertEquals(event.path, path) def test_add_and_get_tasks(self): task1 = Task() task2 = Task() self.assertEqual(self.event.add_task(task1), task1) self.assertEqual(self.event.add_task(task2), task2) self.assertEquals(self.event.get_tasks(), [task1, task2]) def test_prepend_tasks(self): task1 = Task() task2 = Task() self.assertEqual(self.event.prepend_task(task1), task1) self.assertEqual(self.event.prepend_task(task2), task2) self.assertEquals(self.event.get_tasks(), [task2, task1]) def test_remove_task(self): task1 = self.event.add_task(Task()) task2 = self.event.add_task(Task()) task3 = self.event.add_task(Task()) self.event.remove_task(task2) self.assertEquals(self.event.get_tasks(), [task1, task3]) def test_replace_task(self): task1 = self.event.add_task(Task()) task2 = self.event.add_task(Task()) task3 = self.event.add_task(Task()) task4 = Task() task5 = self.event.replace_task(task2, task4) self.assertEquals(self.event.get_tasks(), [task1, task4, task3]) self.assertTrue(task4 is task5) def test_default_matches(self): self.assertEquals(self.event.matches(None), False) def test_default_run(self): self.assertEquals(self.event.run(None), None) def test_default_satisfied(self): self.assertEquals(self.event.satisfied(), True) def test_default_verify(self): self.assertEquals(self.event.verify(), None) def test_default_replay(self): self.assertEquals(self.event.replay(), None) def test_default_restore(self): self.assertEquals(self.event.restore(), None) def test_matches_false(self): task1 = self.event.add_task(Task()) task1.matches = lambda path: True task2 = self.event.add_task(Task()) task2.matches = lambda path: False task3 = self.event.add_task(Task()) task3.matches = lambda path: True self.assertEquals(self.event.matches(None), False) def test_matches_true(self): task1 = self.event.add_task(Task()) task1.matches = lambda path: True task2 = self.event.add_task(Task()) task2.matches = lambda path: True self.assertEquals(self.event.matches(None), True) def test_matches_argument(self): calls = [] task = self.event.add_task(Task()) task.matches = lambda path: calls.append(path) self.event.matches(42) self.assertEquals(calls, [42]) def test_run(self): calls = [] task1 = self.event.add_task(Task()) task1.run = lambda path: calls.append(path) or True task2 = self.event.add_task(Task()) task2.run = lambda path: calls.append(path) or False task3 = self.event.add_task(Task()) task3.run = lambda path: calls.append(path) or None self.assertEquals(self.event.run(42), False) self.assertEquals(calls, [42, 42, 42]) def test_run_errors(self): class MyTask(Task): def __init__(self, id, failed): self.id = id self.failed = failed def run(self, path): if self.failed: raise AssertionError("%d failed" % self.id) event = Event("i.am.a.path") event.add_task(MyTask(1, True)) event.add_task(MyTask(2, False)) event.add_task(MyTask(3, True)) try: event.run("i.am.a.path") except AssertionError, e: message = os.linesep.join(["i.am.a.path", "- 1 failed", "- 3 failed"]) self.assertEquals(str(e), message) else: self.fail("AssertionError not raised") def test_run_errors_with_different_path_representation(self): """When the path representation isn't the same it's shown up.""" class MyTask(Task): def __init__(self, id, failed): self.id = id self.failed = failed def run(self, path): if self.failed: raise AssertionError("%d failed" % self.id) event = Event("i.am.a.path") event.add_task(MyTask(1, True)) event.add_task(MyTask(2, False)) event.add_task(MyTask(3, True)) try: event.run(42) except AssertionError, e: message = os.linesep.join(["i.am.a.path", "- Run: 42", # <== "- 1 failed", "- 3 failed"]) self.assertEquals(str(e), message) else: self.fail("AssertionError not raised") def test_run_errors_need_good_messages(self): class MyTask(Task): def run(self, path): raise AssertionError() self.event.add_task(MyTask()) self.assertRaises(RuntimeError, self.event.run, 42) def test_may_run_user_code(self): """ Tasks that may run user code should be run if a prior failure has already been detected. """ class MyTask(Task): def __init__(self, id, user_code): self.id = id self.user_code = user_code def may_run_user_code(self): return self.user_code def run(self, path): raise AssertionError("%d failed" % self.id) event = Event("i.am.a.path") event.add_task(MyTask(1, False)) event.add_task(MyTask(2, True)) event.add_task(MyTask(3, False)) try: event.run("i.am.a.path") except AssertionError, e: message = os.linesep.join(["i.am.a.path", "- 1 failed", "- 3 failed"]) self.assertEquals(str(e), message) else: self.fail("AssertionError not raised") def test_has_run(self): self.assertFalse(self.event.has_run()) self.event.run(None) self.assertTrue(self.event.has_run()) def test_has_run_reset_on_replay(self): self.event.run(None) self.event.replay() self.assertFalse(self.event.has_run()) def test_may_run(self): calls = [] task1 = Task() task1.may_run = lambda path: calls.append((1, path)) or True task2 = Task() task2.may_run = lambda path: calls.append((2, path)) self.assertEquals(self.event.may_run(42), True) self.event.add_task(task1) self.assertEquals(self.event.may_run(42), True) self.assertEquals(calls, [(1, 42)]) del calls[:] self.event.add_task(task2) self.event.add_task(task1) # Should return on first false. self.assertEquals(self.event.may_run(42), False) self.assertEquals(calls, [(1, 42), (2, 42)]) def test_satisfied_false(self): def raise_error(): raise AssertionError("An error") task1 = self.event.add_task(Task()) task2 = self.event.add_task(Task()) task2.verify = raise_error task3 = self.event.add_task(Task()) self.assertEquals(self.event.satisfied(), False) def test_satisfied_true(self): task1 = self.event.add_task(Task()) task1.satisfied = lambda: True task2 = self.event.add_task(Task()) task2.satisfied = lambda: True self.assertEquals(self.event.satisfied(), True) def test_verify(self): class MyTask(object): def __init__(self, id, failed): self.id = id self.failed = failed def verify(self): if self.failed: raise AssertionError("%d failed" % self.id) event = Event("i.am.a.path") event.add_task(MyTask(1, True)) event.add_task(MyTask(2, False)) event.add_task(MyTask(3, True)) try: event.verify() except AssertionError, e: message = os.linesep.join(["i.am.a.path", "- 1 failed", "- 3 failed"]) self.assertEquals(str(e), message) else: self.fail("AssertionError not raised") def test_verify_errors_need_good_messages(self): class MyTask(Task): def verify(self): raise AssertionError() self.event.add_task(MyTask()) self.assertRaises(RuntimeError, self.event.verify) def test_replay(self): calls = [] task1 = self.event.add_task(Task()) task2 = self.event.add_task(Task()) task1.replay = lambda: calls.append("task1") task2.replay = lambda: calls.append("task2") self.event.replay() self.assertEquals(calls, ["task1", "task2"]) def test_restore(self): calls = [] task1 = self.event.add_task(Task()) task2 = self.event.add_task(Task()) task1.restore = lambda: calls.append("task1") task2.restore = lambda: calls.append("task2") self.event.restore() self.assertEquals(calls, ["task1", "task2"]) class ReplayRestoreEventTest(TestCase): def setUp(self): self.event = ReplayRestoreEvent() def test_never_matches(self): self.assertEquals(self.event.matches(None), False) self.event.add_task(Task()) self.assertEquals(self.event.matches(None), False) class TaskTest(TestCase): def setUp(self): self.task = Task() def test_default_matches(self): self.assertEquals(self.task.matches(None), True) def test_default_may_run(self): self.assertEquals(self.task.may_run(None), True) def test_default_may_run_user_code(self): self.assertEquals(self.task.may_run_user_code(), False) def test_default_run(self): self.assertEquals(self.task.run(None), None) def test_default_verify(self): self.assertEquals(self.task.verify(), None) def test_default_replay(self): self.assertEquals(self.task.replay(), None) def test_default_restore(self): self.assertEquals(self.task.restore(), None) class OnRestoreCallerTest(TestCase): def setUp(self): self.mocker = CleanMocker() self.mock = self.mocker.mock() def test_is_task(self): self.assertTrue(isinstance(OnRestoreCaller(None), Task)) def test_restore(self): calls = [] task = OnRestoreCaller(lambda: calls.append("callback")) self.assertEquals(calls, []) task.restore() self.assertEquals(calls, ["callback"]) task.restore() self.assertEquals(calls, ["callback", "callback"]) class PathMatcherTest(TestCase): def setUp(self): self.mocker = CleanMocker() self.mock = self.mocker.mock() def test_is_task(self): self.assertTrue(isinstance(PathMatcher(None), Task)) def test_create(self): path = object() task = PathMatcher(path) self.assertEquals(task.path, path) def test_matches(self): path = Path(self.mock, None, [Action("getattr", ("attr1",), {})]) task = PathMatcher(path) action = Action("getattr", (), {}, Path(self.mock)) self.assertFalse(task.matches(action.path + action)) action = Action("getattr", ("attr1",), {}, Path(self.mock)) self.assertTrue(task.matches(action.path + action)) def test_recorder(self): path = Path(self.mock, [Action("call", (), {})]) event = Event(path) path_matcher_recorder(self.mocker, event) (task,) = event.get_tasks() self.assertEquals(type(task), PathMatcher) self.assertTrue(task.path is path) def test_is_standard_recorder(self): self.assertTrue(path_matcher_recorder in Mocker.get_recorders()) class RunCounterTest(TestCase): def setUp(self): self.mocker = CleanMocker() self.mock = self.mocker.mock() self.action = Action("getattr", ("attr",), {}, Path(self.mock)) self.path = Path(self.mock, [self.action]) self.event = Event(self.path) def test_is_task(self): self.assertTrue(isinstance(RunCounter(1), Task)) def test_create_one_argument(self): task = RunCounter(2) self.assertEquals(task.min, 2) self.assertEquals(task.max, 2) def test_create_min_max(self): task = RunCounter(2, 3) self.assertEquals(task.min, 2) self.assertEquals(task.max, 3) def test_create_unbounded(self): task = RunCounter(2, None) self.assertEquals(task.min, 2) self.assertEquals(task.max, sys.maxint) def test_run_one_argument(self): task = RunCounter(2) task.run(self.path) task.run(self.path) self.assertRaises(AssertionError, task.run, self.path) def test_run_two_arguments(self): task = RunCounter(1, 2) task.run(self.path) task.run(self.path) self.assertRaises(AssertionError, task.run, self.path) def test_may_run(self): task = RunCounter(1) self.assertEquals(task.may_run(None), True) task.run(self.path) self.assertEquals(task.may_run(None), False) def test_verify(self): task = RunCounter(2) self.assertRaises(AssertionError, task.verify) task.run(self.path) self.assertRaises(AssertionError, task.verify) task.run(self.path) task.verify() self.assertRaises(AssertionError, task.run, self.path) self.assertRaises(AssertionError, task.verify) def test_verify_two_arguments(self): task = RunCounter(1, 2) self.assertRaises(AssertionError, task.verify) task.run(self.path) task.verify() task.run(self.path) task.verify() self.assertRaises(AssertionError, task.run, self.path) self.assertRaises(AssertionError, task.verify) def test_verify_unbound(self): task = RunCounter(1, None) self.assertRaises(AssertionError, task.verify) task.run(self.path) task.verify() task.run(self.path) task.verify() def test_reset_on_replay(self): task = RunCounter(1, 1) task.run(self.path) self.assertRaises(AssertionError, task.run, self.path) task.replay() self.assertRaises(AssertionError, task.verify) task.run(self.path) self.assertRaises(AssertionError, task.run, self.path) def test_recorder(self): class MyTask(Task): pass self.event.add_task(MyTask()) run_counter_recorder(self.mocker, self.event) (task1, task2) = self.event.get_tasks() self.assertEquals(type(task1), ImplicitRunCounter) self.assertEquals(type(task2), MyTask) self.assertTrue(task1.min == 1) self.assertTrue(task1.max == 1) def test_recorder_wont_record_when_count_is_false(self): self.mock.__mocker_count__ = False run_counter_recorder(self.mocker, self.event) self.assertEquals(self.event.get_tasks(), []) def test_removal_recorder(self): """ Events created by getattr actions which lead to other events may be repeated any number of times. """ path1 = Path(self.mock) path2 = path1 + Action("getattr", ("attr",), {}, path1) path3 = path2 + Action("getattr", ("attr",), {}, path2) path4 = path3 + Action("call", (), {}, path3) path5 = path4 + Action("call", (), {}, path4) event3 = self.mocker.add_event(Event(path3)) event2 = self.mocker.add_event(Event(path2)) event5 = self.mocker.add_event(Event(path5)) event4 = self.mocker.add_event(Event(path4)) event2.add_task(RunCounter(1)) event2.add_task(ImplicitRunCounter(1)) event2.add_task(RunCounter(1)) event3.add_task(RunCounter(1)) event3.add_task(ImplicitRunCounter(1)) event3.add_task(RunCounter(1)) event4.add_task(RunCounter(1)) event4.add_task(ImplicitRunCounter(1)) event4.add_task(RunCounter(1)) event5.add_task(RunCounter(1)) event5.add_task(ImplicitRunCounter(1)) event5.add_task(RunCounter(1)) # First, when the previous event isn't a getattr. run_counter_removal_recorder(self.mocker, event5) self.assertEquals(len(event2.get_tasks()), 3) self.assertEquals(len(event3.get_tasks()), 3) self.assertEquals(len(event4.get_tasks()), 3) self.assertEquals(len(event5.get_tasks()), 3) # Now, for real. run_counter_removal_recorder(self.mocker, event4) self.assertEquals(len(event2.get_tasks()), 3) self.assertEquals(len(event3.get_tasks()), 2) self.assertEquals(len(event4.get_tasks()), 3) self.assertEquals(len(event5.get_tasks()), 3) task1, task2 = event3.get_tasks() self.assertEquals(type(task1), RunCounter) self.assertEquals(type(task2), RunCounter) def test_removal_recorder_with_obj(self): self.mocker.add_recorder(run_counter_recorder) self.mocker.add_recorder(run_counter_removal_recorder) obj = self.mocker.mock() obj.x.y()() events = self.mocker.get_events() self.assertEquals(len(events), 4) self.assertEquals(len(events[0].get_tasks()), 0) self.assertEquals(len(events[1].get_tasks()), 0) self.assertEquals(len(events[2].get_tasks()), 1) self.assertEquals(len(events[3].get_tasks()), 1) def test_reset_on_replay_with_mock(self): mock = self.mocker.mock() mock() self.mocker.count(1) self.mocker.replay() mock() self.assertRaises(AssertionError, mock) self.mocker.replay() mock() self.assertRaises(AssertionError, mock) def test_is_standard_recorder(self): self.assertTrue(run_counter_recorder in Mocker.get_recorders()) self.assertTrue(run_counter_removal_recorder in Mocker.get_recorders()) class MockReturnerTest(TestCase): def setUp(self): self.mocker = CleanMocker() self.mock = self.mocker.mock() self.action = Action("getattr", ("attr",), {}, Path(self.mock)) self.path = Path(self.mock, [self.action]) self.event = Event(self.path) def test_is_task(self): self.assertTrue(isinstance(MockReturner(self.mocker), Task)) def test_create(self): task = MockReturner(self.mocker) mock = task.run(self.path) self.assertTrue(isinstance(mock, Mock)) self.assertEquals(mock.__mocker__, self.mocker) self.assertTrue(mock.__mocker_path__.matches(self.path)) def test_recorder(self): path1 = Path(self.mock) path2 = path1 + Action("getattr", ("attr",), {}, path1) path3 = path2 + Action("getattr", ("attr",), {}, path2) path4 = path3 + Action("call", (), {}, path3) event2 = self.mocker.add_event(Event(path2)) event3 = self.mocker.add_event(Event(path3)) event4 = self.mocker.add_event(Event(path4)) self.assertEquals(len(event2.get_tasks()), 0) self.assertEquals(len(event3.get_tasks()), 0) self.assertEquals(len(event4.get_tasks()), 0) # Calling on 4 should add it only to the parent. mock_returner_recorder(self.mocker, event4) self.assertEquals(len(event2.get_tasks()), 0) self.assertEquals(len(event3.get_tasks()), 1) self.assertEquals(len(event4.get_tasks()), 0) (task,) = event3.get_tasks() self.assertEquals(type(task), MockReturner) self.assertEquals(task.mocker, self.mocker) # Calling on it again shouldn't do anything. mock_returner_recorder(self.mocker, event4) self.assertEquals(len(event2.get_tasks()), 0) self.assertEquals(len(event3.get_tasks()), 1) self.assertEquals(len(event4.get_tasks()), 0) def test_is_standard_recorder(self): self.assertTrue(mock_returner_recorder in Mocker.get_recorders()) class FunctionRunnerTest(TestCase): def setUp(self): self.mocker = CleanMocker() self.mock = self.mocker.mock() self.action = Action("call", (1, 2), {"c": 3}, Path(self.mock)) self.path = Path(self.mock, None, [self.action]) self.event = Event(self.path) def test_is_task(self): self.assertTrue(isinstance(FunctionRunner(None), Task)) def test_may_run_user_code(self): task = FunctionRunner(None) self.assertEquals(task.may_run_user_code(), True) def test_run(self): task = FunctionRunner(lambda *args, **kwargs: repr((args, kwargs))) result = task.run(self.path) self.assertEquals(result, "((1, 2), {'c': 3})") def test_run_with_object(self): task = FunctionRunner(lambda *args, **kwargs: repr((args, kwargs)), with_root_object=True) self.path.root_object = 4 result = task.run(self.path) self.assertEquals(result, "((4, 1, 2), {'c': 3})") class PathExecuterTest(TestCase): def setUp(self): self.mocker = CleanMocker() def test_is_task(self): self.assertTrue(isinstance(PathExecuter(), Task)) def test_run(self): class C(object): pass obj = C() obj.x = C() obj.x.y = lambda a, b: a+b path = Path(None, obj, [Action("getattr", ("x",), {}), Action("getattr", ("y",), {}), Action("call", (1,), {"b": 2})]) task = PathExecuter() self.assertEquals(task.run(path), 3) def test_run_with_result_callback(self): class C(object): def x(self, arg): return 41 + arg obj = C() path = Path(None, obj, [Action("getattr", ("x",), {}), Action("call", (1,), {})]) calls = [] result_callback = lambda result: calls.append(result) task = PathExecuter(result_callback) self.assertEquals(task.get_result_callback(), result_callback) self.assertEquals(task.run(path), 42) self.assertEquals(calls, [42]) class OrdererTest(TestCase): def setUp(self): self.mocker = CleanMocker() self.mock = self.mocker.mock() self.action = Action("call", (1, 2, Path(self.mock)), {"c": 3}) self.path = Path(self.mock, [self.action]) def test_is_task(self): self.assertTrue(isinstance(Orderer(self.path), Task)) def test_path(self): self.assertEquals(Orderer(self.path).path, self.path) def test_has_run(self): orderer = Orderer(self.path) self.assertFalse(orderer.has_run()) orderer.run(self.path) self.assertTrue(orderer.has_run()) def test_reset_on_replay(self): orderer = Orderer(self.path) orderer.run(self.path) orderer.replay() self.assertFalse(orderer.has_run()) def test_reset_on_replay_with_mock(self): self.mocker.add_recorder(path_matcher_recorder) mock = self.mocker.mock() self.mocker.order(mock(1), mock(2)) self.mocker.replay() mock(1) mock(2) self.mocker.replay() self.assertRaises(AssertionError, mock, 2) def test_add_and_get_dependencies(self): orderer = Orderer(self.path) orderer.add_dependency(1) orderer.add_dependency(2) self.assertEquals(orderer.get_dependencies(), [1, 2]) def test_may_run(self): orderer1 = Orderer(self.path) orderer2 = Orderer(self.path) orderer2.add_dependency(orderer1) self.assertFalse(orderer2.may_run(None)) self.assertTrue(orderer1.may_run(None)) orderer1.run(self.path) self.assertTrue(orderer2.may_run(None)) def test_run_with_missing_dependency(self): orderer1 = Orderer("path1") orderer2 = Orderer("path2") orderer2.add_dependency(orderer1) try: orderer2.run(None) except AssertionError, e: self.assertEquals(str(e), "Should be after: path1") else: self.fail("AssertionError not raised") class SpecCheckerTest(TestCase): def setUp(self): class C(object): def __call__(self, a, b, c=3): pass def normal(self, a, b, c=3): pass def varargs(self, a, b, c=3, *args): pass def varkwargs(self, a, b, c=3, **kwargs): pass def varargskwargs(self, a, b, c=3, *args, **kwargs): pass def klass(cls, a, b, c=3): pass klass = classmethod(klass) def static(a, b, c=3): pass static = staticmethod(static) def noargs(self): pass def klassnoargs(cls): pass klassnoargs = classmethod(klassnoargs) def staticnoargs(): pass staticnoargs = staticmethod(staticnoargs) self.cls = C self.mocker = CleanMocker() self.mock = self.mocker.mock(self.cls) def path(self, *args, **kwargs): action = Action("call", args, kwargs, Path(self.mock)) return action.path + action def good(self, method_names, args_expr): if type(method_names) is not list: method_names = [method_names] for method_name in method_names: task = SpecChecker(getattr(self.cls, method_name, None)) path = eval("self.path(%s)" % args_expr) self.assertEquals(task.may_run(path), True) try: task.run(path) except AssertionError: self.fail("AssertionError raised with self.cls.%s(%s)" % (method_name, args_expr)) def bad(self, method_names, args_expr): if type(method_names) is not list: method_names = [method_names] for method_name in method_names: task = SpecChecker(getattr(self.cls, method_name, None)) path = eval("self.path(%s)" % args_expr) self.assertEquals(task.may_run(path), False) try: task.run(path) except AssertionError: pass else: self.fail("AssertionError not raised with self.cls.%s(%s)" % (method_name, args_expr)) def test_get_method(self): task = SpecChecker(self.cls.noargs) self.assertEquals(task.get_method(), self.cls.noargs) def test_is_standard_recorder(self): self.assertTrue(spec_checker_recorder in Mocker.get_recorders()) def test_is_task(self): self.assertTrue(isinstance(SpecChecker(self.cls.normal), Task)) def test_error_message(self): task = SpecChecker(self.cls.normal) try: task.run(self.path(1)) except AssertionError, e: self.assertEquals(str(e), "Specification is normal(a, b, c=3): " "'b' not provided") else: self.fail("AssertionError not raised") def test_verify_unexistent_method(self): task = SpecChecker(None) try: task.verify() except AssertionError, e: self.assertEquals(str(e), "Method not found in real specification") else: self.fail("AssertionError not raised") def test_unsupported_object_for_getargspec(self): from zlib import adler32 # If that fails, this test has to change because either adler32 has # changed, or the implementation of getargspec has changed. self.assertRaises(TypeError, inspect.getargspec, adler32) try: task = SpecChecker(adler32) task.run(self.path("asd")) except TypeError, e: self.fail("TypeError: %s" % str(e)) def test_recorder(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj.noargs() getattr, call = self.mocker.get_events() self.assertEquals(getattr.get_tasks(), []) (task,) = call.get_tasks() self.assertEquals(type(task), SpecChecker) self.assertEquals(task.get_method(), self.cls.noargs) def test_recorder_with_unexistent_method(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj.unexistent() getattr, call = self.mocker.get_events() self.assertEquals(getattr.get_tasks(), []) (task,) = call.get_tasks() self.assertEquals(type(task), SpecChecker) self.assertEquals(task.get_method(), None) def test_recorder_second_action_isnt_call(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj.noargs.x event1, event2 = self.mocker.get_events() self.assertEquals(event1.get_tasks(), []) self.assertEquals(event2.get_tasks(), []) def test_recorder_first_action_isnt_getattr(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj.__mocker_act__("anyother", ("attr",))() event1, event2 = self.mocker.get_events() self.assertEquals(event1.get_tasks(), []) self.assertEquals(event2.get_tasks(), []) def test_recorder_more_than_two_actions(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj.noargs().x event1, event2, event3 = self.mocker.get_events() self.assertEquals(len(event1.get_tasks()), 0) self.assertEquals(len(event2.get_tasks()), 1) self.assertEquals(len(event3.get_tasks()), 0) def test_recorder_with_call_on_object(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj() (call,) = self.mocker.get_events() (task,) = call.get_tasks() self.assertEquals(type(task), SpecChecker) self.assertEquals(task.get_method(), self.cls.__call__) def test_recorder_more_than_one_action_with_direct_call(self): self.mocker.add_recorder(spec_checker_recorder) obj = self.mocker.mock(spec=self.cls) obj().x event1, event2 = self.mocker.get_events() self.assertEquals(len(event1.get_tasks()), 1) self.assertEquals(len(event2.get_tasks()), 0) def test_noargs(self): methods = ["noargs", "klassnoargs", "staticnoargs"] self.good(methods, "") self.bad(methods, "1") self.bad(methods, "a=1") def test_args_and_kwargs(self): methods = ["__call__", "normal", "varargs", "varkwargs", "varargskwargs", "static", "klass"] self.good(methods, "1, 2") self.good(methods, "1, 2, 3") self.good(methods, "1, b=2") self.good(methods, "1, b=2, c=3") self.good(methods, "a=1, b=2") self.good(methods, "a=1, b=2, c=3") def test_too_much(self): methods = ["__call__", "normal", "static", "klass"] self.bad(methods, "1, 2, 3, 4") self.bad(methods, "1, 2, d=4") def test_missing(self): methods = ["__call__", "normal", "varargs", "varkwargs", "varargskwargs", "static", "klass"] self.bad(methods, "") self.bad(methods, "1") self.bad(methods, "c=3") self.bad(methods, "a=1") self.bad(methods, "b=2, c=3") def test_duplicated_argument(self): methods = ["__call__", "normal", "varargs", "varkwargs", "varargskwargs", "static", "klass"] self.bad(methods, "1, 2, b=2") def test_varargs(self): self.good("varargs", "1, 2, 3, 4") self.bad("varargs", "1, 2, 3, 4, d=3") def test_varkwargs(self): self.good("varkwargs", "1, 2, d=3") self.bad("varkwargs", "1, 2, 3, 4, d=3") def test_varargskwargs(self): self.good("varargskwargs", "1, 2, 3, 4, d=3") def test_unexistent(self): self.bad("unexistent", "") class ProxyReplacerTest(TestCase): def setUp(self): self.mocker = CleanMocker() import calendar self.mock = Mock(self.mocker, object=calendar) self.task = ProxyReplacer(self.mock) def tearDown(self): self.task.restore() def test_is_task(self): self.assertTrue(isinstance(ProxyReplacer(None), Task)) def test_mock(self): mock = object() task = ProxyReplacer(mock) self.assertEquals(task.mock, mock) def test_defaults_to_not_installed(self): import calendar self.assertEquals(type(calendar), ModuleType) def test_install(self): self.task.replay() import calendar self.assertEquals(type(calendar), Mock) self.assertTrue(calendar is self.mock) def test_install_protects_mock(self): self.task.replay() self.assertEquals(type(self.mock.__mocker_object__), ModuleType) def test_install_protects_path(self): self.task.replay() self.assertEquals(type(self.mock.__mocker_path__.root_object), ModuleType) def test_deinstall_protects_task(self): self.task.replay() self.task.restore() self.assertEquals(type(self.task.mock), Mock) def test_install_protects_anything_with_mocker_replace_false(self): class C(object): def __init__(self): import calendar self.calendar = calendar self.__mocker_replace__ = False obj = C() self.task.replay() self.assertEquals(type(self.mock.__mocker_path__.root_object), ModuleType) def test_install_on_object(self): class C(object): def __init__(self): import calendar self.calendar = calendar obj = C() self.task.replay() self.assertEquals(type(obj.calendar), Mock) self.assertTrue(obj.calendar is self.mock) def test_install_on_submodule(self): from os import path mock = Mock(self.mocker, object=path) task = ProxyReplacer(mock) task.replay() try: self.assertEquals(type(os.path), Mock) self.assertTrue(os.path is mock) finally: task.restore() def test_uninstall_on_restore(self): self.task.replay() self.task.restore() import calendar self.assertEquals(type(calendar), ModuleType) self.assertEquals(calendar.__name__, "calendar") def test_uninstall_from_object(self): class C(object): def __init__(self): import calendar self.calendar = calendar obj = C() self.task.replay() self.task.restore() self.assertEquals(type(obj.calendar), ModuleType) self.assertEquals(obj.calendar.__name__, "calendar") def test_uninstall_from_submodule(self): from os import path mock = Mock(self.mocker, object=path) task = ProxyReplacer(mock) self.assertEquals(type(os.path), ModuleType) task.replay() task.restore() self.assertEquals(type(os.path), ModuleType) class PatcherTest(TestCase): def setUp(self): self.mocker = Mocker() self.patcher = Patcher() self.C = type("C", (object,), {}) self.D = type("D", (self.C,), {}) self.E = type("E", (), {}) class MockStub(object): def __mocker_act__(self, kind, args=(), kwargs={}, object=None): return (kind, args, kwargs, object) self.MockStub = MockStub def test_is_task(self): self.assertTrue(isinstance(Patcher(), Task)) def test_undefined_repr(self): self.assertEquals(repr(Undefined), "Undefined") def test_is_monitoring_unseen_class_kind(self): self.assertFalse(self.patcher.is_monitoring(self.C, "kind")) def test_monitor_class(self): self.patcher.monitor(self.C, "kind") self.assertTrue(self.patcher.is_monitoring(self.C, "kind")) def test_monitor_subclass(self): self.patcher.monitor(self.C, "kind") self.assertTrue(self.patcher.is_monitoring(self.D, "kind")) def test_monitor_unknown_class(self): self.patcher.monitor(self.C, "kind") self.assertFalse(self.patcher.is_monitoring(self.E, "kind")) def test_is_monitoring_unseen_instance(self): obj = self.E() self.patcher.monitor(self.C, "kind") self.assertFalse(self.patcher.is_monitoring(obj, "kind")) def test_is_monitoring_instance_explicitly_monitored(self): obj = self.C() self.patcher.monitor(obj, "kind") self.assertTrue(self.patcher.is_monitoring(obj, "kind")) def test_is_monitoring_instance_monitored_by_class(self): obj = self.D() self.patcher.monitor(self.D, "kind") self.assertTrue(self.patcher.is_monitoring(obj, "kind")) def test_patch_attr(self): self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.C.__dict__.get("attr"), "patch") def test_patch_attr_and_restore(self): self.patcher.patch_attr(self.C, "attr", "patch") self.patcher.restore() self.assertTrue("attr" not in self.C.__dict__) def test_patch_attr_and_restore_to_original(self): self.C.attr = "original" self.patcher.patch_attr(self.C, "attr", "patch") self.patcher.restore() self.assertEquals(self.C.__dict__.get("attr"), "original") def test_get_unpatched_attr_unpatched_undefined(self): self.assertEquals(self.patcher.get_unpatched_attr(self.C, "attr"), Undefined) def test_get_unpatched_attr_unpatched(self): self.C.attr = "original" self.assertEquals(self.patcher.get_unpatched_attr(self.C, "attr"), "original") def test_get_unpatched_attr_defined_on_superclass(self): self.C.attr = "original" self.assertEquals(self.patcher.get_unpatched_attr(self.D, "attr"), "original") def test_get_unpatched_attr_defined_on_superclass_patched_on_sub(self): self.C.attr = "original" self.patcher.patch_attr(self.D, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.D, "attr"), "original") def test_get_unpatched_attr_patched_originally_undefined(self): self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.C, "attr"), Undefined) def test_get_unpatched_attr_patched(self): self.C.attr = "original" self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.C, "attr"), "original") def test_get_unpatched_attr_on_instance_originally_undefined(self): self.assertEquals(self.patcher.get_unpatched_attr(self.C(), "attr"), Undefined) def test_get_unpatched_attr_on_instance(self): self.C.attr = "original" self.assertEquals(self.patcher.get_unpatched_attr(self.D(), "attr"), "original") def test_get_unpatched_attr_on_instance_defined_on_superclass(self): self.C.attr = "original" self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.D(), "attr"), "original") def test_get_unpatched_attr_on_instance_with_descriptor(self): self.C.attr = property(lambda self: "original") self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.D(), "attr"), "original") def test_get_unpatched_attr_on_subclass_with_descriptor(self): calls = [] class Property(object): def __get__(self, obj, cls): calls.append((obj, cls)) return "original" self.C.attr = Property() self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.D, "attr"), "original") self.assertEquals(calls, [(None, self.D)]) def test_get_unpatched_attr_on_instance_with_fake_descriptor(self): class BadProperty(object): def __init__(self): # On real, __get__ must be on the class, not on the instance. self.__get__ = lambda self, obj, cls=None: "original" prop = BadProperty() self.C.attr = prop self.patcher.patch_attr(self.C, "attr", "patch") self.assertEquals(self.patcher.get_unpatched_attr(self.D(), "attr"), prop) def test_replay_with_monitored_class(self): self.patcher.monitor(self.C, "call") self.patcher.replay() self.assertEquals(type(self.C.__dict__["__call__"]), PatchedMethod) def test_replay_with_monitored_instance(self): self.patcher.monitor(self.C(), "call") self.patcher.replay() self.assertEquals(type(self.C.__dict__["__call__"]), PatchedMethod) def test_replay_getattr(self): self.patcher.monitor(self.C, "getattr") self.patcher.replay() self.assertEquals(type(self.C.__dict__["__getattribute__"]), PatchedMethod) def test_restore(self): self.patcher.monitor(self.C, "call") self.patcher.replay() self.patcher.restore() self.assertTrue("__call__" not in self.C.__dict__) def test_restore_twice_does_nothing(self): self.patcher.monitor(self.C, "call") self.patcher.replay() self.patcher.restore() self.C.__call__ = "original" self.patcher.restore() self.assertTrue(self.C.__dict__.get("__call__"), "original") def test_patched_call_on_instance(self): self.patcher.monitor(self.C, "call") obj = self.C() obj.__mocker_mock__ = self.MockStub() self.patcher.replay() result = obj(1, a=2) self.assertEquals(result, ("call", (1,), {"a": 2}, obj)) def test_patched_call_on_class(self): self.patcher.monitor(self.C, "call") self.C.__mocker_mock__ = self.MockStub() self.patcher.replay() obj = self.C() result = obj(1, a=2) self.assertEquals(result, ("call", (1,), {"a": 2}, obj)) def test_patched_call_on_class_edge_case(self): """Only "getattr" kind should passthrough on __mocker_* arguments.""" self.patcher.monitor(self.C, "call") self.C.__mocker_mock__ = self.MockStub() self.patcher.replay() obj = self.C() result = obj("__mocker_mock__") self.assertEquals(result, ("call", ("__mocker_mock__",), {}, obj)) def test_patched_getattr_on_class(self): self.patcher.monitor(self.C, "getattr") self.C.__mocker_mock__ = self.MockStub() self.patcher.replay() obj = self.C() result = obj.attr self.assertEquals(result, ("getattr", ("attr",), {}, obj)) def test_patched_getattr_on_unmonitored_object(self): obj1 = self.C() obj1.__mocker_mock__ = self.MockStub() self.patcher.monitor(obj1, "getattr") obj2 = self.C() obj2.attr = "original" self.patcher.replay() self.assertEquals(obj1.attr, ("getattr", ("attr",), {}, obj1)) self.assertEquals(obj2.attr, "original") def test_patched_getattr_on_different_instances(self): def build_getattr(original): def __getattribute__(self, name): if name == "attr": return original return object.__getattribute__(self, name) return __getattribute__ self.C.__getattribute__ = build_getattr("originalC") self.D.__getattribute__ = build_getattr("originalD") class MockStub(object): def __init__(self, id): self.id = id def __mocker_act__(self, kind, args=(), kwargs={}, object=None): return self.id obj1, obj2, obj3, obj4, obj5, obj6 = [self.C() for i in range(6)] obj7, obj8, obj9 = [self.D() for i in range(3)] obj2.__mocker_mock__ = MockStub(2) self.patcher.monitor(obj2, "getattr") obj5.__mocker_mock__ = MockStub(5) self.patcher.monitor(obj5, "getattr") obj8.__mocker_mock__ = MockStub(8) self.patcher.monitor(obj8, "getattr") self.patcher.replay() self.assertEquals(obj1.attr, "originalC") self.assertEquals(obj2.attr, 2) self.assertEquals(obj3.attr, "originalC") self.assertEquals(obj4.attr, "originalC") self.assertEquals(obj5.attr, 5) self.assertEquals(obj6.attr, "originalC") self.assertEquals(obj7.attr, "originalD") self.assertEquals(obj8.attr, 8) self.assertEquals(obj9.attr, "originalD") def test_patched_getattr_execute_getattr(self): class C(object): def __getattribute__(self, attr): if attr == "attr": return "original" action = Action("getattr", ("attr",), {}) obj = C() self.patcher.monitor(obj, "getattr") self.patcher.replay() self.assertEquals(self.patcher.execute(action, obj), "original") def test_execute_getattr_on_unexistent(self): action = Action("getattr", ("attr",), {}) obj = self.C() self.patcher.monitor(obj, "getattr") self.patcher.replay() self.assertRaises(AttributeError, self.patcher.execute, action, obj) def test_patched_real_getattr_on_different_instances(self): def build_getattr(original): def __getattr__(self, name): if name == "attr": return original return object.__getattr__(self, name) return __getattr__ self.C.__getattr__ = build_getattr("originalC") self.D.__getattr__ = build_getattr("originalD") class MockStub(object): def __init__(self, id): self.id = id def __mocker_act__(self, kind, args=(), kwargs={}, object=None): return self.id obj1, obj2, obj3, obj4, obj5, obj6 = [self.C() for i in range(6)] obj7, obj8, obj9 = [self.D() for i in range(3)] obj2.__mocker_mock__ = MockStub(2) self.patcher.monitor(obj2, "getattr") obj5.__mocker_mock__ = MockStub(5) self.patcher.monitor(obj5, "getattr") obj8.__mocker_mock__ = MockStub(8) self.patcher.monitor(obj8, "getattr") self.patcher.replay() self.assertEquals(obj1.attr, "originalC") self.assertEquals(obj2.attr, 2) self.assertEquals(obj3.attr, "originalC") self.assertEquals(obj4.attr, "originalC") self.assertEquals(obj5.attr, 5) self.assertEquals(obj6.attr, "originalC") self.assertEquals(obj7.attr, "originalD") self.assertEquals(obj8.attr, 8) self.assertEquals(obj9.attr, "originalD") def test_patched_real_getattr_execute_getattr(self): class C(object): def __getattr__(self, attr): if attr == "attr": return "original" action = Action("getattr", ("attr",), {}) obj = C() self.patcher.monitor(obj, "getattr") self.patcher.replay() self.assertEquals(self.patcher.execute(action, obj), "original") def test_execute_call(self): class C(object): def __call__(self, *args, **kwargs): return (args, kwargs) action = Action("call", (1,), {"a": 2}) obj = C() self.patcher.monitor(obj, "call") self.patcher.replay() self.assertEquals(self.patcher.execute(action, obj), ((1,), {"a": 2})) def test_recorder_class_getattr(self): self.C.method = lambda: None mock = self.mocker.patch(self.C) mock.method() self.mocker.result("mocked") self.mocker.replay() self.assertEquals(self.C().method(), "mocked") self.assertRaises(AssertionError, self.C().method) def test_recorder_instance_getattr(self): self.C.attr = "original" obj1 = self.C() obj2 = self.C() mock = self.mocker.patch(obj1) mock.attr self.mocker.result("mocked") self.mocker.replay() self.assertEquals(obj1.attr, "mocked") self.assertRaises(AssertionError, getattr, obj1, "attr") self.assertEquals(obj2.attr, "original") self.assertRaises(AttributeError, getattr, obj1, "unexistent") def test_recorder_passthrough(self): class C(object): def __init__(self): self.result = "original" # Value on object's dictionary. def method(self): return self.result mock = self.mocker.patch(C) mock.method() self.mocker.passthrough() self.mocker.replay() obj = C() self.assertEquals(obj.method(), "original") self.assertRaises(AssertionError, obj.method) def test_original_exception_raised(self): class C(object): def use_non_existing_attribute(self): return self.bad_attribute mock = self.mocker.patch(C) mock.any_other_method() self.mocker.replay() obj = C() try: obj.use_non_existing_attribute() except AttributeError, error: message = "'C' object has no attribute 'bad_attribute'" self.assertEquals(message, str(error)) def main(): try: unittest.main() finally: print if coverage: coverage.stop() (filename, executed, missing, missing_human) = coverage.analysis("mocker.py") if missing: print "WARNING: Some statements were not executed:" print coverage.report(["mocker.py"]) else: print "Tests covered 100% of statements!" else: print "WARNING: No coverage test performed (missing coverage.py)" print if __name__ == "__main__": main()