wrote simple mocking helper methods and classes
[wifi-assistant] / package / test / unit / pie.py
1 import sys
2
3 def pprint(*args):
4     if False:
5         for a in args:
6             try:
7                 sys.stdout.write(a.__str__())
8             except:
9                 try:
10                     sys.stdout.write(a.__doc__)
11                 except:
12                     sys.stdout.write('BUG - FIXME')
13             sys.stdout.write(' ')
14         sys.stdout.write('\n')
15         sys.stdout.flush()
16
17 class Mock():
18     def __init__(self):
19         pprint("Mock.__init__")
20         self._methods = {}
21         self._replay = False
22         
23     def __getattr__(self, value):
24         pprint("Mock.__getattr__", value)
25         if self._methods.has_key(value):
26             pprint("returning mocked method")
27             return self._methods[value]
28         if self._replay:
29             class inner():
30                 def __init__(self, method_name):
31                     self._method_name = method_name
32                     self._recorded_calls = []
33                     self._args = None
34                     self._kwargs = None
35                 def __call__(self, *args, **kwargs):
36                     pprint("REPLAYING", self.getName(), args, kwargs)
37                     self._recorded_calls.append((args, kwargs))
38                     self._args = args
39                     self._kwargs = kwargs
40                 def getName(self):
41                     return self._method_name
42                 def getNumberOfInvocations(self):
43                     return len(self._recorded_calls)
44                 def verify(self, args, kwargs):
45                     if args != self._args or kwargs != self._kwargs:
46                         raise Exception("No call for %s with arguments %s - actual: %s" % (value, args, self._args))
47                     return True
48                     
49             pprint("returning 'empty' method", value)
50             empty = inner(value)
51             self.register(value, empty)
52             return empty
53         raise AttributeError("Mock doesn't contain attribute", value)
54         pprint("returning super method")
55         return Object.__getattr__.call(self, value)
56         
57     def replay(self):
58         pprint("Mock.__replay__")
59         self._replay = True
60         
61     def register(self, methodName, mock):
62         pprint("Mock.__register__", methodName)
63         self._methods[methodName] = mock
64     
65     def getMethodMock(self, methodName):
66         pprint("Mock.getMethodMock", methodName)
67         if self._methods.has_key(methodName):
68             return self._methods[methodName]
69         return None
70
71 class MethodMock():
72     def __init__(self, mock, args, kwargs):
73         pprint("MethodMock.__init__", args, kwargs)
74         self.target = mock
75         self._method_name = args[0]
76         mock.register(self._method_name, self)
77         self.args = args[1:]
78         self.kwargs = kwargs
79         self._recorded_calls = []
80         self._canned_response = None
81         self._canned_args = None
82         self._canned_args_set = False
83     
84     def willReturn(self, args):
85         pprint(self.getName(), "willReturn", args)
86         self._canned_response = args
87         
88     def verify(self, args, kwargs):
89         pprint("MethodMock.verify", args, kwargs)
90         recorded_args, recorded_kwargs = self._recorded_calls.pop()
91         pprint("          .verify", recorded_args, recorded_kwargs)
92         return args == recorded_args and kwargs == recorded_kwargs
93     
94     def getName(self):
95         return self._method_name
96     
97     def getNumberOfInvocations(self):
98         return len(self._recorded_calls)
99     
100     def __call__(self, *args, **kwargs):
101         if self._canned_args_set: # replay
102             pprint("MethodMock.__call__ REPLAYING", self.getName(), args, kwargs, "returning", self._canned_response)
103             self._recorded_calls.append((args, kwargs))
104             return self._canned_response
105         else:
106             pprint("MethodMock.__call__ RECORDING", self.getName(), args, kwargs)
107             self._canned_args_set = True
108             self._canned_args = args
109             return self
110         
111 class given():
112     def __init__(self, mock):
113         pprint("given.__init__")
114         self.target = mock
115     
116     def __getattr__(self, *args, **kwargs):
117         pprint("given.__getattr__", args, kwargs)
118         return MethodMock(self.target, args, kwargs) 
119         
120
121 class MethodCallVerifier():
122     def __init__(self, methodMock, times):
123         self.method = methodMock
124         self.times = times
125     def __call__(self, *args, **kwargs):
126         pprint("MethodCallVerifier.__call__", self.method, args, kwargs)
127         # FIXME: verify times times
128         calls = self.method.getNumberOfInvocations()
129         min_calls = self.times.getMinimumNumberOfTimes()
130         max_calls = self.times.getMaximumNumberOfTimes()
131         if calls < min_calls:
132             raise Exception("Expected at least %s calls to %s, got %s" % (min_calls, self.method.getName(), calls))
133         if calls > max_calls:
134             raise Exception("Expected at most %s calls to %s, got %s" % (max_calls, self.method.getName(), calls))
135         if calls == 0:
136             return
137             
138         match = self.method.verify(args, kwargs)
139         if match:
140             pprint("Yes, call for", self.method.getName(), "matched arguments", args, kwargs)
141         else:
142             pprint("Nope, call for", self.method.getName(), "didn't match arguments", args, kwargs)
143             raise Exception("mock verification failed")
144
145 def empty(*args, **kwargs):
146     pass
147
148 class once():
149     def __call__(self):
150         pass
151     def getMinimumNumberOfTimes(self):
152         return 1
153     def getMaximumNumberOfTimes(self):
154         return 1
155
156 class never():
157     def __call__(self):
158         pass
159     def getMinimumNumberOfTimes(self):
160         return 0
161     def getMaximumNumberOfTimes(self):
162         return 0
163
164 class verify():
165     def __init__(self, mock, times=None):
166         pprint("verify.__init__")
167         self.target = mock
168         self.times = times
169         if self.times is None:
170             self.times = once()
171         
172     def __getattr__(self, methodName):
173         pprint("verify.__getattr__", methodName)
174         method_mock = self.target.getMethodMock(methodName)
175         if method_mock is None:
176             if self.times.getMinimumNumberOfTimes() > 0:
177                 raise Exception("method " + methodName + " was never called")
178             return empty
179         return MethodCallVerifier(method_mock, self.times)
180         
181