diff options
author | Gustavo Niemeyer <gustavo@niemeyer.net> | 2007-10-31 22:31:53 -0400 |
---|---|---|
committer | Gustavo Niemeyer <gustavo@niemeyer.net> | 2007-10-31 22:31:53 -0400 |
commit | 9c4134a7f47ac0065ebfef3c72d527a7f3f23339 (patch) | |
tree | 136230981a9877849c8eaa690af398cd76e216b1 | |
parent | db9037f7c5fa1ebd3fae117abc2eb89ee431c01b (diff) | |
download | mocker-9c4134a7f47ac0065ebfef3c72d527a7f3f23339.tar.gz |
Added support for "delattr" and "contains" kinds, and finished
support for "setattr".
-rw-r--r-- | mocker.py | 32 | ||||
-rwxr-xr-x | test.py | 91 |
2 files changed, 114 insertions, 9 deletions
@@ -745,9 +745,18 @@ class Mock(object): return super(Mock, self).__setattr__(name, value) return self.__mocker_act__("setattr", (name, value)) + def __delattr__(self, name): + return self.__mocker_act__("delattr", (name,)) + def __call__(self, *args, **kwargs): return self.__mocker_act__("call", args, kwargs) + def __contains__(self, value): + return self.__mocker_act__("contains", (value,)) + + # When adding a new action kind here, also add support for it on + # Action.execute() and Path.__str__(). + def find_object_name(obj, depth=0): """Try to detect how the object is named on a previous scope.""" @@ -816,11 +825,16 @@ class Action(object): kind = self.kind if kind == "getattr": result = getattr(object, self.args[0]) + elif kind == "setattr": + result = setattr(object, self.args[0], self.args[1]) + elif kind == "delattr": + result = delattr(object, self.args[0]) elif kind == "call": result = object(*self.args, **self.kwargs) + elif kind == "contains": + result = self.args[0] in object else: - raise RuntimeError("Don't know how to apply %r kind" - % self.kind) + raise RuntimeError("Don't know how to execute %r kind." % kind) self._execute_cache[id(object)] = result return result @@ -882,19 +896,25 @@ class Path(object): def __str__(self): """Transform the path into a nice string such as obj.x.y('z').""" - attrs = [self.root_mock.__mocker_name__ or "<mock>"] + result = self.root_mock.__mocker_name__ or "<mock>" for action in self.actions: if action.kind == "getattr": - attrs.append(action.args[0]) + result = "%s.%s" % (result, action.args[0]) + elif action.kind == "setattr": + result = "%s.%s = %r" % (result, action.args[0], action.args[1]) + elif action.kind == "delattr": + result = "del %s.%s" % (result, action.args[0]) elif action.kind == "call": args = [repr(x) for x in action.args] for pair in sorted(action.kwargs.iteritems()): args.append("%s=%r" % pair) - attrs[-1] += "(%s)" % ", ".join(args) + result = "%s(%s)" % (result, ", ".join(args)) + elif action.kind == "contains": + result = "%r in %s" % (action.args[0], result) else: raise RuntimeError("Don't know how to format kind %r" % action.kind) - return ".".join(attrs) + return result class SpecialArgument(object): @@ -914,15 +914,39 @@ class ActionTest(unittest.TestCase): class C(object): pass obj = C() - obj.x = C() - action = Action("getattr", ("x",), {}) - self.assertEquals(action.execute(obj), obj.x) + 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_contains(self): + obj = set(["a"]) + action = Action("contains", ("a",), {}) + self.assertEquals(action.execute(obj), True) + action = Action("contains", ("b",), {}) + self.assertEquals(action.execute(obj), False) + def test_execute_caching(self): values = iter(range(10)) obj = lambda: values.next() @@ -1144,6 +1168,15 @@ class PathTest(unittest.TestCase): path += Action("getattr", ("x",), {}) self.assertEquals(str(path), "obj.attr.x") + 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()") @@ -1152,6 +1185,10 @@ class PathTest(unittest.TestCase): [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_getattr_call(self): path = Path(self.mock, None, [Action("getattr", ("x",), {}), Action("getattr", ("y",), {}), @@ -1435,6 +1472,14 @@ class MockTest(unittest.TestCase): 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 @@ -1443,6 +1488,14 @@ class MockTest(unittest.TestCase): 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_passthrough_on_unexpected(self): class StubMocker(object): def act(self, path): @@ -1497,6 +1550,38 @@ class MockTest(unittest.TestCase): 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() + mock = mocker.mock() + check = [] + for name, attr in Mock.__dict__.iteritems(): + if not name.startswith("__mocker_") and hasattr(attr, "__call__"): + 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(unittest.TestCase): |