summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Niemeyer <gustavo@niemeyer.net>2007-10-31 22:31:53 -0400
committerGustavo Niemeyer <gustavo@niemeyer.net>2007-10-31 22:31:53 -0400
commit9c4134a7f47ac0065ebfef3c72d527a7f3f23339 (patch)
tree136230981a9877849c8eaa690af398cd76e216b1
parentdb9037f7c5fa1ebd3fae117abc2eb89ee431c01b (diff)
downloadmocker-9c4134a7f47ac0065ebfef3c72d527a7f3f23339.tar.gz
Added support for "delattr" and "contains" kinds, and finished
support for "setattr".
-rw-r--r--mocker.py32
-rwxr-xr-xtest.py91
2 files changed, 114 insertions, 9 deletions
diff --git a/mocker.py b/mocker.py
index 6e88b7c..7d0db79 100644
--- a/mocker.py
+++ b/mocker.py
@@ -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):
diff --git a/test.py b/test.py
index dc7a73c..b07d604 100755
--- a/test.py
+++ b/test.py
@@ -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):