Permalink
Browse files

more cleanup, more passing tests

  • Loading branch information...
1 parent 3ac4d60 commit 07289b0be5e66d17c7134948bd619b70880988f1 @timbertson committed Dec 27, 2010
View
@@ -4,5 +4,6 @@
#from mockerror import *
#from stub import *
from matchers import *
+from callrecord import *
__version__ = '0.3.0'
View
@@ -1,14 +1,20 @@
import sys, traceback, os
+__all__ = ['Call']
+
class Call(object):
- def __init__(self, args, kwargs, stack = True):
+ def __init__(self, args, kwargs, stack = False):
self.tuple = (args, kwargs)
- self.args = args if len(args) > 0 else None
- self.kwargs = kwargs if len(kwargs) > 0 else None
+ self.args = args
+ self.kwargs = kwargs
if stack is True:
self._stack = traceback.extract_stack(sys._getframe())
+ @classmethod
+ def like(cls, *a, **kw):
+ return cls(a, kw)
+
def _concise_stack(self):
stack = self._stack
relevant_line = stack[-3]
@@ -35,18 +41,23 @@ def __ne__(self, other):
return not self.__eq__(other)
def play(self, function):
+ print repr((self.args, self.kwargs))
return function(*self.args, **self.kwargs)
-
- def __str__(self):
+
+ def desc(self, include_stack=False):
if self.empty:
- arg_desc = "No arguments"
+ arg_desc = "()"
else:
sep = ', '
- args = None if self.args is None else sep.join(map(repr, self.args))
- kwargs = None if self.kwargs is None else sep.join(["%s=%r" % (key, val) for key, val in self.kwargs.items()])
- arg_desc = sep.join(filter(lambda x: x is not None, (args, kwargs)))
+ args = sep.join(map(repr, self.args))
+ kwargs = sep.join(["%s=%r" % (key, val) for key, val in self.kwargs.items()])
+ arg_desc = "(%s)" % (sep.join(filter(None, (args, kwargs))),)
try:
- return "%-24ls // %s" % (arg_desc, self._concise_stack())
- except (IndexError, AttributeError):
+ if include_stack:
+ arg_desc = "%-24ls // %s" % (arg_desc, self._concise_stack())
+ finally:
return arg_desc
+ def __str__(self):
+ return self.desc(include_stack=True)
+
View
@@ -1,9 +1,8 @@
-#__all__ = (
-# 'raw_mock',
-# 'mock',
-# 'mock_on',
-# 'expect',
-#)
+__all__ = (
+ 'MockTransaction',
+ '_setup',
+ '_teardown',
+)
__unittest = True
View
@@ -1,218 +0,0 @@
-"""
-MockAnchor provides a way to rollback mocks at the end of every unit test.
-Instead of:
- os.system = mock
-use:
- mock_on(os).system
-
-after the current test is over, os.system will revert to its previous behaviour.
-
-mock_on(parent) returns a MockAnchor. Every attribute accessed (or set) via this instance
-will replace the parent's attribute of the same name, and return a MockWrapper for the newly
-inserted mock.
-"""
-
-import sys
-
-from lib.realsetter import RealSetter
-from mockwrapper import MockWrapper
-from silentmock import SilentMock, raw_mock
-from lib import singletonclass
-
-def when(parent, quiet = False):
- return MockAnchor(parent, quiet)
-
-def expect(parent):
- return ExpectedMockAnchor(parent)
-
-def _special_method(name):
- return name.startswith('__') and name.endswith('__')
-
-class MockAnchor(RealSetter):
- _active = []
- def __new__(cls, parent, quiet=False):
- for anchor in cls._active:
- if anchor._parent is parent:
- return anchor
-
- # this should use super, but I've no idea how...
- supertype = RealSetter
- self = supertype.__new__(cls)
- self._init_records()
- self._real_set(_parent = parent)
- self._real_set(_quiet = quiet)
- self.__class__._active.append(self)
-
- return self
-
- def _init_records(self):
- self._real_set(_children = {})
- self._real_set(_items = {})
- self._real_set(_real_children = {})
- self._real_set(_real_items = {})
-
- def _child_store(self, in_dict):
- return self._items if in_dict else self._children
-
- def _real_child_store(self, in_dict):
- return self._real_items if in_dict else self._real_children
-
- def _backup_child(self, name, in_dict):
- try:
- # if it's replacing a real object, store it here for later
- real_child = self._accessor_func(in_dict)(self._parent, name)
- except (AttributeError, KeyError):
- if not self._quiet:
- print >> sys.stderr, "Warning: object %s has no %s \"%s\"" % (self._parent, "key" if in_dict else "attribute", name)
- return
-
- if isinstance(real_child, SilentMock):
- raise TypeError("Replacing a mock with another mock is a profoundly bad idea.\n" +
- "Try re-using mock \"%s\" instead" % (name,))
- self._real_child_store(in_dict)[name] = real_child
- return real_child
-
- def _make_mock_if_required(self, name, in_dict=False):
- if name not in self._children:
- target = self._get_target_for_method(name, in_dict)
- real_child = self._backup_child(name, in_dict)
- new_child = MockWrapper(raw_mock(name=name), proxied=real_child)
- self._child_store(in_dict)[name] = new_child
- self._insertion_func(in_dict)(target, name, new_child._mock)
- return self._child_store(in_dict)[name]
-
- def _should_ever_assign_to_super(self, in_dict):
- return not (in_dict or isinstance(self._parent, type))
-
- def _get_target_for_method(self, name, in_dict):
- if not self._should_ever_assign_to_super(in_dict):
- return self._parent
-
- if not _special_method(name):
- return self._parent
-
- # otherwise, we'll be assigning to the *class* of self._parent
- # - so we better make it unique
- singletonclass.ensure_singleton_class(self._parent)
- return type(self._parent)
-
- @classmethod
- def _reset_all(cls):
- for mock in cls._active:
- mock._reset()
- cls._active = []
-
- # interchangeable deletion, getter and setter methods
- def _insertion_func(self, in_dict):
- return self._setitem if in_dict else self._setattr
-
- def _deletion_func(self, in_dict):
- return self._delitem if in_dict else self._delattr
-
- def _accessor_func(self, in_dict):
- return self._getitem if in_dict else self._getattr
-
- @staticmethod
- def _setitem(target, name, val):
- target[name] = val
-
- @staticmethod
- def _setattr(target, name, val):
- setattr(target, name, val)
-
- @staticmethod
- def _getitem(target, name):
- return target[name]
-
- @staticmethod
- def _getattr(target, name):
- return getattr(target, name)
-
- @staticmethod
- def _delitem(target, name):
- try:
- del target[name]
- except StandardError:
- target[name] = None
-
- @staticmethod
- def _delattr(target, name):
- try:
- delattr(target, name)
- except StandardError:
- setattr(target, name, None)
-
- def _restore_children(self, in_dict):
- """
- Restore all children from _real_children / _real_items
- (depending on in_dict) to self._parent.
- If a child does not appear in _real_*, it is deleted from self._parent.
- If that fails, it's set to None.
- """
- children = self._child_store(in_dict)
- real_children = self._real_child_store(in_dict)
- assign = self._insertion_func(in_dict)
- del_ = self._deletion_func(in_dict)
-
- for name in children:
- if name in real_children:
- assign(self._parent, name, real_children[name])
- else:
- del_(self._parent, name)
-
- def _reset(self):
- """reset all children and items, then remove all record of them"""
- self._restore_parent_class()
- self._restore_children(in_dict = True)
- self._restore_children(in_dict = False)
- self._init_records()
-
- def _restore_parent_class(self):
- singletonclass.revert_singleton_class(self._parent)
-
- def __getattribute__(self, attr):
- try:
- ret = super(type(self), self).__getattribute__(attr)
- except AttributeError: ret = None
-
- # all special methods are accessed via type.__getattr__ when
- # used as a result of a python language feature
- # (eg len(x) instead of x.__len__()).
- # So any time the instance receives __getattribute__, it must
- # be an explicit access (by the programmer), for the purpose of
- # stubbing it.
- # __class__ is special. Don't even try.
- if ret is not None:
- if (not _special_method(attr)) or attr == '__class__':
- return ret
-
- return self._make_mock_if_required(attr)
-
- def __setattr__(self, attr, val):
- child = self._make_mock_if_required(attr)
- child.return_value = val
-
- def __getitem__(self, attr):
- return self._make_mock_if_required(attr, in_dict=True)
-
- def __setitem__(self, attr, val):
- child = self._make_mock_if_required(attr, in_dict= True)
- child.return_value = val
-
- def expects(self, methodname):
- return getattr(self, methodname).is_expected
-
-class ExpectedMockAnchor(MockAnchor):
- def _make_mock_if_required(self, *a, **kw):
- ret = super(type(self), self)._make_mock_if_required(*a, **kw)
- ret.expect()
-
-
-
-class MockExpression(object):
- def __init__(self):
- self.expected
-
- def expected_at_least(self, num):
- self.expected_count = lambda x: x
-
View
@@ -1,10 +1,19 @@
from matchers import Matcher, SplatMatcher
from mockerror import MockError
+from callrecord import Call
from transaction import MockTransaction
from lib.singletonclass import ensure_singleton_class
__unittest = True
+__all__ = [
+ 'when',
+ 'expect',
+ 'stub',
+ 'mock',
+ 'modify',
+]
+
def when(obj):
return GetWrapper(lambda name: mock_when(obj, name))
@@ -14,7 +23,7 @@ def expect(obj):
def stub(obj):
return GetWrapper(lambda name: mock_stub(obj, name))
-def mock(name, create_unknown_children=True):
+def mock(name='unnamed mock', create_unknown_children=True):
return RecursiveStub(name, create_unknown_children)
def modify(obj):
@@ -76,6 +85,7 @@ def copying(self, other):
return self
def __setattr__(self, name, val):
+ print repr(name)
self._real_set(**{name:val})
return self._callback(name, val)
@@ -127,42 +137,12 @@ def __getattr__(self, name):
return obj
def __call__(self, *a, **kw):
- self.received_calls.append(Call(a,kw))
+ self.received_calls.append(Call(a,kw, stack=True))
return None
-class Call(object):
- @classmethod
- def like(cls, *a, **kw):
- return cls(a, kw)
-
- def __init__(self, args, kwargs):
- self.args = args
- self.kwargs = kwargs
- self.tuple = (self.args, self.kwargs)
-
- def __eq__(self, other):
- if isinstance(other, type(self)):
- return self.tuple == other.tuple
- else:
- return self.tuple == other
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __str__(self):
- if self.kwargs:
- kwargs = ", " + ", ".join(["%s=%r" % (k,v) for k,v in self.kwargs.items()])
- else:
- kwargs = ''
- return "(%s%s)" % (", ".join(map(repr, self.args)), kwargs)
-
- def play(self, function):
- return function(*self.args, **self.kwargs)
-
def stub_method(obj, name):
- assert MockTransaction.started
+ assert MockTransaction.started, "Mock transaction has not been started. Make sure you are inheriting from mocktest.TestCase"
if _special_method(name) and not isinstance(obj, type):
- print "special method: %s"% (name,)
ensure_singleton_class(obj)
obj = type(obj)
add_teardown_for_attr(obj, name)
@@ -193,14 +173,14 @@ def _new_act(self, name):
return act
def __call__(self, *a, **kw):
- call = Call(a, kw)
+ call = Call(a, kw, stack=True)
self.calls.append(call)
for act in reversed(self.acts):
if act._matches(call):
return act._act_upon(call)
else:
act_condition_descriptions = [" - " + act.condition_description for act in self.acts]
- raise TypeError("stubbed method %r received unexpected arguments: %s\nAllowable argument conditions are:\n%s" % (self.name, call,"\n".join(act_condition_descriptions)))
+ raise TypeError("stubbed method %r received unexpected arguments: %s\nAllowable argument conditions are:\n%s" % (self.name, call.desc(),"\n".join(act_condition_descriptions)))
def _verify(self):
for act in self.acts:
Oops, something went wrong.

0 comments on commit 07289b0

Please sign in to comment.