summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--mocker.py14
-rwxr-xr-xtest.py83
3 files changed, 93 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index 6ba674c..886c9cd 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+0.9.3 (2007-11-XX)
+==================
+
+- Introduced automatic test coverage verification as part of
+ the test suite, based on the 'coverage' module by Ned Batchelder,
+ to ensure that it continues to have 100% of statement coverage.
+
+
0.9.2 (2007-11-22)
==================
diff --git a/mocker.py b/mocker.py
index 65cb417..6c9db68 100644
--- a/mocker.py
+++ b/mocker.py
@@ -39,7 +39,7 @@ class expect(object):
"""This is a simple helper that allows a different call-style.
With this class one can comfortably do chaining of calls to the
- mocker object responsible by the object being handler. For instance::
+ mocker object responsible by the object being handled. For instance::
expect(obj.attr).result(3).count(1, 2)
@@ -282,15 +282,6 @@ class classinstancemethod(object):
return bound_method
-class State(object):
-
- def __init__(self, name):
- self._name = name
-
- def __repr__(self):
- return self._name
-
-
class MockerBase(object):
"""Controller of mock objects.
@@ -1602,6 +1593,7 @@ class RunCounter(Task):
raise AssertionError("Performed less times than expected.")
raise AssertionError("Performed more times than expected.")
+
class ImplicitRunCounter(RunCounter):
"""RunCounter inserted by default on any event.
@@ -1806,7 +1798,7 @@ def global_replace(remove, install):
for referrer in gc.get_referrers(remove):
if (type(referrer) is dict and
referrer.get("__mocker_replace__", True)):
- for key, value in referrer.iteritems():
+ for key, value in referrer.items():
if value is remove:
referrer[key] = install
diff --git a/test.py b/test.py
index f4f8291..cc88bcd 100755
--- a/test.py
+++ b/test.py
@@ -9,6 +9,15 @@ import gc
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,
@@ -874,6 +883,13 @@ class MockerTest(unittest.TestCase):
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
@@ -1530,6 +1546,15 @@ class ActionTest(unittest.TestCase):
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
@@ -1976,6 +2001,12 @@ class MatchParamsTest(unittest.TestCase):
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), {})
@@ -2017,6 +2048,7 @@ class MatchParamsTest(unittest.TestCase):
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})
@@ -2469,6 +2501,13 @@ class EventTest(unittest.TestCase):
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_satisfied_false(self):
def raise_error():
raise AssertionError("An error")
@@ -2508,6 +2547,13 @@ class EventTest(unittest.TestCase):
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())
@@ -3264,6 +3310,9 @@ class PatcherTest(unittest.TestCase):
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"))
@@ -3361,6 +3410,18 @@ class PatcherTest(unittest.TestCase):
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):
@@ -3547,5 +3608,25 @@ class PatcherTest(unittest.TestCase):
self.assertRaises(AssertionError, obj.method)
+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__":
- unittest.main()
+ main()