Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

updated documentation for 0.5, added sphinx doc

  • Loading branch information...
commit 524e210fb17e38b5faf70c7e6e025c29d56874fa 1 parent aa0f3e7
Tim Cuthbertson authored
3  .gitignore
@@ -4,3 +4,6 @@ dist
4 4 .coverage
5 5 *.egg-info
6 6 *.tmproj
  7 +doc/build
  8 +.*
  9 +0inst
37 LICENCE
... ... @@ -1,30 +1,15 @@
1   -BSD Licence:
  1 +Copyright (C) 2010 Tim Cuthbertson
2 2
3   -Redistribution and use in source and binary forms, with or without
4   -modification, are permitted provided that the following conditions are
5   -met:
  3 +This program is free software: you can redistribute it and/or modify
  4 +it under the terms of the GNU General Public License as published by
  5 +the Free Software Foundation, either version 3 of the License, or
  6 +(at your option) any later version.
6 7
  8 +This program is distributed in the hope that it will be useful,
  9 +but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11 +GNU General Public License for more details.
7 12
8   - * Redistributions of source code must retain the above copyright
9   - notice, this list of conditions and the following disclaimer.
  13 +You should have received a copy of the GNU General Public License
  14 +along with this program. If not, see <http://www.gnu.org/licenses/>.
10 15
11   - * Redistributions in binary form must reproduce the above
12   - copyright notice, this list of conditions and the following
13   - disclaimer in the documentation and/or other materials provided
14   - with the distribution.
15   -
16   - * Neither the name of Michael Foord nor the name of Voidspace
17   - may be used to endorse or promote products derived from this
18   - software without specific prior written permission.
19   -
20   -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21   -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22   -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23   -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24   -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25   -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26   -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28   -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29   -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30   -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
92 Makefile
... ... @@ -0,0 +1,92 @@
  1 +# Makefile for Sphinx documentation
  2 +#
  3 +
  4 +# You can set these variables from the command line.
  5 +SPHINXOPTS =
  6 +SPHINXBUILD = sphinx-build
  7 +PAPER =
  8 +BUILDDIR = doc/build
  9 +
  10 +# Internal variables.
  11 +PAPEROPT_a4 = -D latex_paper_size=a4
  12 +PAPEROPT_letter = -D latex_paper_size=letter
  13 +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
  14 +
  15 +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest copy doc
  16 +
  17 +help:
  18 + @echo "Please use \`make <target>' where <target> is one of"
  19 + @echo " html to make standalone HTML files"
  20 + @echo " dirhtml to make HTML files named index.html in directories"
  21 + @echo " pickle to make pickle files"
  22 + @echo " json to make JSON files"
  23 + @echo " htmlhelp to make HTML files and a HTML help project"
  24 + @echo " qthelp to make HTML files and a qthelp project"
  25 + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
  26 + @echo " changes to make an overview of all changed/added/deprecated items"
  27 + @echo " linkcheck to check all external links for integrity"
  28 + @echo " doctest to run all doctests embedded in the documentation (if enabled)"
  29 +
  30 +doc: html copy
  31 +copy:
  32 + rsync -avz doc/build/html/ ~/Sites/gfxmonk/dist/doc/mocktest/
  33 +clean:
  34 + -rm -rf $(BUILDDIR)/*
  35 +
  36 +html:
  37 + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
  38 + @echo
  39 + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
  40 +
  41 +dirhtml:
  42 + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
  43 + @echo
  44 + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
  45 +
  46 +pickle:
  47 + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
  48 + @echo
  49 + @echo "Build finished; now you can process the pickle files."
  50 +
  51 +json:
  52 + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
  53 + @echo
  54 + @echo "Build finished; now you can process the JSON files."
  55 +
  56 +htmlhelp:
  57 + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
  58 + @echo
  59 + @echo "Build finished; now you can run HTML Help Workshop with the" \
  60 + ".hhp project file in $(BUILDDIR)/htmlhelp."
  61 +
  62 +qthelp:
  63 + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
  64 + @echo
  65 + @echo "Build finished; now you can run "qcollectiongenerator" with the" \
  66 + ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
  67 + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mocktest.qhcp"
  68 + @echo "To view the help file:"
  69 + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mocktest.qhc"
  70 +
  71 +latex:
  72 + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
  73 + @echo
  74 + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
  75 + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
  76 + "run these through (pdf)latex."
  77 +
  78 +changes:
  79 + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
  80 + @echo
  81 + @echo "The overview file is in $(BUILDDIR)/changes."
  82 +
  83 +linkcheck:
  84 + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
  85 + @echo
  86 + @echo "Link check complete; look for any errors in the above output " \
  87 + "or in $(BUILDDIR)/linkcheck/output.txt."
  88 +
  89 +doctest:
  90 + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
  91 + @echo "Testing of doctests in the sources finished, look at the " \
  92 + "results in $(BUILDDIR)/doctest/output.txt."
507 README.markdown
Source Rendered
... ... @@ -1,507 +0,0 @@
1   -how about:
2   -
3   -# heirarchial mocking:
4   -when(obj).meth().then_return(foo)
5   -
6   -when(obj).meth.with(x,y,z).then_return(foo)
7   -
8   -replace(obj).property.with(some_stub)
9   -
10   -expect(obj).meth.with(fdsf).once()
11   -
12   -# direct mocking:
13   -# how about we just reserve mock_* and with_* for mocktest?
14   -# when() and expect() can still access the mock puppet, but nobody else?
15   -# mock_calls,
16   -x = mock("foo")
17   -x = mock("foo").with(x=1,y=2)
18   -x = mock("foo").with_children(x=1,y=2)
19   -x = mock("foo").with_methods(x=1,y=2)
20   -x = mock("foo").with_spec(bob)
21   -
22   -when(x).meth.then_return(fdjsafj)
23   -expect(x).meth.once
24   -
25   -x.mock_calls.should == [1,2,3]
26   -s.mock_return = ___
27   -s.mock_freeze()
28   -s.mock_unfreeze()
29   -
30   -when(obj)().then_return(foo) # possible with the below as well? probably not...
31   -when(obj).__call__.then_return(result)
32   -
33   -
34   -raw mocks go away... a mock() call will yield a combination raw mock that has with_* and mock_* methods, and can be puppeted via when(), expect(), replace(), etc...
35   -
36   -
37   -
38   -
39   -##
40   -
41   -
42   -#test inheritance
43   -
44   -
45   -inherit setup/teardown (but no test methods) from another class:
46   -
47   -class MyTest(TestCase.skeleton): pass
48   -
49   -class MyTest(skeleton(TestCase)): pass
50   -
51   -
52   -
53   -
54   -
55   -## mocktest (version 0.3)
56   -... is a powerful and easy-to-use mocking library, inspired by rspec and
57   -similar in many ways to Michael Foord's popular Mock module.
58   -
59   -The main features are:
60   -
61   - - powerful expectation matching behaviour for mock objects
62   - - automatic verification of expectations (before each test's tearDown)
63   - - automatic rollback of inserted mock objects after each test
64   -
65   -It's released under the BSD licence (see the LICENCE file).
66   -
67   -Source / Readme / Issues:
68   -[http://github.com/gfxmonk/mocktest/tree/master](http://github.com/gfxmonk/mocktest/tree/master)
69   -
70   -Cheese shop entry:
71   -[http://pypi.python.org/pypi/mocktest](http://pypi.python.org/pypi/mocktest/0.1)
72   -
73   -### Important notes for this version
74   -
75   -In mocktest 0.3, a few key objects and attributes have been renamed:
76   -
77   - - the `mock_wrapper()` function is now just called `mock()`
78   - - to get a raw mock from a mock wrapper, you now use `.raw` instead of `.mock`
79   -
80   -To sum up, where you would previously use `mock_wrapper().mock` you now would
81   -use `mock().raw`. The new names are more concise and less confusing to new users.
82   -
83   -### Where did it come from?
84   -I am a big fan of rspec, but less of a fan of ruby as a whole.
85   -I wanted a to use rspec's powerful `should_receive()` and associated matchers
86   -with my python mock objects.
87   -
88   -mocktest is by no means a port of rspec - it is smaller and simpler, and a lot
89   -more pythonic.
90   -
91   -### what *are* mocks?
92   -
93   -What are mocks used for? mocks can pretend to be pretty much any object. Mocks
94   -record what happens to them (accessors, method calls, etc) and allow you to
95   -verify that this is what you expected. Replace a database connection with a mock
96   -and make sure the right commands are being sent to your database - without the
97   -overhead and trouble of using an actual database. Replace os.system with a mock,
98   -and supply your own response to shell commands. Mocks can be used to satisfy
99   -dependencies or simulate external conditions in your program so you can focus
100   -on unit-level testing.
101   -
102   ----
103   -# mocktest
104   -
105   -## TestCase
106   -
107   -When using mocktest, you should always use `mocktest.TestCase` instead of
108   -`unittest.TestCase`. Mocktest's version is almost identical, but automatically
109   -calls the required setup and teardown hooks for the mocktest library.
110   -
111   -There is one important addition to the `mocktest.TestCase` class:
112   -
113   - * `assertRaises(exception_type, callable, < ... >)`
114   -
115   -Where additional args can be:
116   -
117   - * `args=(arg1,arg2)`
118   - * Fails unless the arguments provided to the exception constructor match the
119   - given args
120   - * `message="some string"`
121   - * Fails unless the error message (i.e. str(exception)) is equal to this
122   - message
123   - * `matches="string"` or `matches=re.compile("match_string", custom_flags)`
124   - * Just like message, except a regex.search is required to return a match
125   - instead of requiring the strings to be identical
126   -
127   -This was adapted from [http://code.activestate.com/recipes/307970/](http://code.activestate.com/recipes/307970/)
128   -
129   ----
130   -## mocks
131   -
132   -mocktest is still a young framework, and is likely to evolve. While the
133   -inspiration is from rspec, a lot of the mechanics differ either necessarily
134   -because of differences between ruby and python, and a bunch of things were done
135   -differently to make things cleaner.
136   -
137   -mocks in mocktest have 3 components. This might sound like two more than you
138   -would need, but bear with me:
139   -
140   - * **raw mock**: a raw mock is a minimal mock object that can be put wherever
141   - you need it. It records interaction that happens to it, but it can't
142   - distinguish between interaction as part of your test and interaction caused
143   - by the rest of the program.
144   -
145   - Some mock frameworks only have this object, but adding methods for
146   - controlling and inspecting a mock interferes with the actual mock behaviour
147   - itself. For this reason, mocktest has a puppet-master of sorts:
148   -
149   - * **mock wrapper**: a mock wrapper is how you talk to a raw mock
150   - behind-the-scenes. It allows you to set the return value for a method,
151   - or see how many times and with what arguments a raw mock has been called.
152   - In your unit test source code, you will mostly be interacting with mock
153   - wrappers to define behaviour and specify your expectations.
154   -
155   - * **mock anchor**: finally, there is one piece missing in the puzzle. You
156   - have a mock, and you talk to it through a mock wrapper. But how do you
157   - insert it where it needs to go? A mock anchor latches on to a root
158   - object, and records every mock you create on it. Creating a mock called
159   - "some\_method" on a mock anchor will attach it to parent.some\_method.
160   - And more importantly, when your unit test is done it will revert
161   - parent.some_method to what it was before.
162   -
163   - By using a mock anchor, you ensure that your mocks never live past the
164   - lifespan of your test case - this can cause havok in other mock
165   - frameworks.
166   -
167   -So, how do you use all of these things?
168   -
169   - anchor = mock_on(some_object)
170   -
171   -creates a **mock anchor** attached to some\_object.
172   -
173   - wrapper = anchor.foo
174   -
175   -creates a **raw mock** called `foo`, and attaches it to some\_object.foo. The
176   -value of this expression is a **mock wrapper** linked to the newly-created
177   -some_object.foo raw mock.
178   -
179   -If your mock is not attached to anything, you can create a standalone mock
180   -wrapper:
181   -
182   - wrapper = mock()
183   -
184   -you can get the raw mock (to provide to your code) with:
185   -
186   - raw_mock = wrapper.raw
187   -
188   -and if you just have a raw mock object, you can get a wrapper for it by calling:
189   -
190   - wrapper = mock(raw_mock)
191   -
192   -This might seem a little confusing, but hopefully the examples below will help.
193   -
194   ----
195   -### Mock customisation
196   -
197   -A mock has a few options for specifying its behaviour:
198   -
199   - wrapper = mock()
200   - wrapper.name = "my mock"
201   - wrapper.return_value = "result!"
202   -
203   -which will result in:
204   -
205   - >>> raw_mock = wrapper.raw
206   - >>> str(raw_mock)
207   - 'my mock'
208   -
209   - >>> raw_mock()
210   - 'result!'
211   -
212   -The other property your mock wrapper has is:
213   -
214   - def my_action(*args):
215   - print "called with: %r" % (args,)
216   - return "result..."
217   - wrapper.action = my_action
218   -
219   -resulting in:
220   -
221   - >>> wrapper.raw('a','b','c')
222   - called with: ['a','b','c']
223   - 'result...'
224   -
225   -*note*: You cannot use both action and return_value on the same mock, you'll get
226   -a `MockError`. If you want to have an action and particular return value, return the
227   -value from the action.
228   -
229   -Because setting properties like this is a little verbose, mock wrapper objects
230   -provide some helpful methods. These methods all return the mock wrapper itself,
231   -so you can chain them together.
232   -
233   - mock().named('my mock')
234   - mock().returning(10)
235   - mock().with_action(lambda x: x + 1)
236   -
237   -In addition, there are some additional methods which don't directly
238   -relate to attributes:
239   -
240   - mock().raising(IOError)
241   - mock().raising(IOError('permission denied'))
242   -
243   -`raising` takes an exception class or instance and raises it when the mock is
244   -called. This overwrites the mock's action attribute (and will fail if you have
245   -already set an action).
246   -
247   -
248   -By default, calling `raw_mock.some_attribute` will force `some_attribute` to be
249   -added to the mock. If you don't want this behaviour, you can lock down the mock
250   -using:
251   -
252   - mock().frozen()
253   -
254   -This will raise an `AttributeError` when any new attribute is accessed (or set)
255   -on the mock.
256   -
257   - mock().with_children('x', 'y', z='zed')
258   - mock().with_methods('x','y', z='zed')
259   - mock().with_spec(some_object)
260   -
261   -Children and methods are similar. They take in any number of string arguments
262   -and keyword arguments. String arguments ensure that an attribute of that name
263   -exists on the mock. Keyword arguments specify its value, as well.
264   -
265   -The difference between `methods` and `children` is that the value of a method
266   -is used for a child's return_value:
267   -
268   - >>> wrapper = mock().with_methods('y', z='zed')
269   - >>> wrapper.raw.z()
270   - 'zed'
271   -
272   -whereas child values are used as-is:
273   -
274   - >>> wrapper = mock().with_children('y', z='zed')
275   - >>> wrapper.raw.z
276   - 'zed'
277   -
278   -If you have an object that you want to mimic, you can use:
279   -
280   - mock().with_spec(some_object)
281   -
282   -If `some_object` has attributes "foo" and "bar", so too will your mock. The
283   -values for these attributes are mocks; they do not copy the `spec_object`'s
284   -attribute values.
285   -
286   -Calling `with_methods`, `with_children` or `with_spec` has the side effect of
287   -freezing the mock. Any attributes that aren't already on the mock cannot be
288   -added. If you want to control this yourself, use `wrapper.frozen()` and
289   -`wrapper.unfrozen()`
290   -
291   -
292   -If you want to, you can also override special methods on a mock:
293   -
294   - >>> wrapper = mock().with_children( __len__ = lambda x: 5 )
295   - >>> len(wrapper.raw)
296   - 5
297   -
298   -There's a bit of black magic to special method overriding, so please send bug
299   -reports if you find something that doesn't work.
300   -
301   ----
302   -### Expectations
303   -
304   -Having earlier said that mocktest is not rspec, here are a bunch of useful
305   -examples ported from the
306   -[rspec documentation](http://rspec.info/documentation/mocks/message_expectations.html)
307   -
308   -The basic setup of a test case is identical to using unittest.TestCase:
309   -
310   - from mocktest import *
311   -
312   - class MyTestClass(TestCase):
313   - def setUp(self):
314   - # common setup actions...
315   -
316   - def tearDown(self):
317   - # common teardown actions...
318   -
319   - def test_feature_a(self):
320   - #test the functionality in feature a
321   -
322   - def test_feature_b(self):
323   - #test the functionality in feature b
324   -
325   -#### Expecting calls
326   -
327   - mock_os = mock_on(os)
328   - mock_os.system.is_expected
329   -
330   -This will fail your test unless os.system() is called at least once during
331   -the current test case (the check is made right before the `tearDown()` method
332   -is executed)
333   -
334   -If you don't want an anchored mock, you can use:
335   -
336   - wrapper = mock()
337   - raw_mock = wrapper.raw
338   - wrapper.is_expected
339   -
340   -You can then pass raw_mock into a function and ensure that it is called. But
341   -you should **not** set `os.system = raw_mock`. This will change `os.system`
342   -for the life of your tests, and will almost certainly mess up the rest of your
343   -test cases. That is why the `mock_on()` function exists to automatically
344   -clean up your mocks.
345   -
346   -#### Multiplicites of calls
347   -
348   -The default `is_expected` ensures that your method is called at least once.
349   -There are other options:
350   -
351   - mock_anchor.method.is_expected.no_times() # shouldn't be called
352   - mock_anchor.method.is_expected.once() # once (and no more)
353   - mock_anchor.method.is_expected.twice()
354   - mock_anchor.method.is_expected.thrice() # (isn't thrice a great word?)
355   -
356   - mock_anchor.method.is_expected.exactly(4).times
357   - mock_anchor.method.is_expected.at_least(10).times
358   - mock_anchor.method.is_expected.at_most(2).times
359   -
360   -this also works just fine:
361   -
362   - mock_anchor.method.is_expected.at_most(2)
363   -
364   -("times" is unnecessary, but it helps for readability)
365   -
366   -#### Expecting Arguments
367   -
368   - mock_anchor.method.is_expected.with(<args>)
369   -
370   -e.g:
371   -
372   - mock_anchor.method.is_expected.with_args(1, 2, 3)
373   - mock_anchor.method.is_expected.with_args(1, 2, 3, foo='bar').once()
374   - mock_anchor.method.is_expected.with_args() # No arguments allowed
375   -
376   -*Note:* When adding conditions to a call, the multiplicity (number of
377   -calls) is checked _after_ the other conditions.
378   -This means that while the following will fail:
379   -
380   - mock_anchor.method.is_expected.once()
381   - myobj.action('a')
382   - myobj.action('b')
383   -
384   -this will succeed:
385   -
386   - mock_anchor.method.is_expected.once().with('a')
387   - myobj.action('a')
388   - myobj.action('b')
389   -
390   -This is the same way that rspec works, and it is the most flexible,
391   -since you can always put a bound on the total invocations by adding a
392   -non-conditional multiplicity check:
393   -
394   - mock_anchor.method.is_expected.twice()
395   -
396   -(you can apply as many `is_expected`'s to a single mock as you like)
397   -
398   -#### Argument Constraints
399   -
400   -When you don't know the exact arguments, you can supply a checking function.
401   -If this function does not return True, the expectation fails:
402   -
403   - mock_anchor.method.is_expected.where_args(lambda arg1, arg2: arg1 == arg2)
404   - mock_anchor.method.is_expected.where_args(lambda arg: isinstance(arg, dict))
405   -
406   -It doesn't have to be an inline lambda expression:
407   -
408   - def check_args(*args, **kwargs):
409   - if len(args) > 3:
410   - return False
411   - if 'bad_argument' in kwargs:
412   - return False
413   - return True
414   -
415   - mock_anchor.method.is_expected.where_args(check_args)
416   -
417   -#### Proxying
418   -
419   -Proxying options are confusingly similar to argument constraints. But where argument
420   -constraints validate the arguments that the mock is called with, proxying controls
421   -weather the mock intercepts a method call in the first place. An example:
422   -
423   - class MyObject(object):
424   - def do_something(self, some_number):
425   - return some_number + 10
426   - obj = MyObject()
427   -
428   - # (note the use of `obj` to match the implicit `self` paramater)
429   - wrapper = mock_on(obj).do_something.with_args(obj, 5).returning(500)
430   - mock_do_something = wrapper.raw
431   -
432   - # now if the arguments we give to the mock don't match what we supplied to
433   - # with_args, the call will go ahead just as if we hadn't set a mock on obj:
434   -
435   - assert mock_do_something(1) == 11
436   - assert mock_do_something(2) == 12
437   -
438   - # but if the arguments do match:
439   - assert mock_do_something(5) == 500
440   -
441   - # note that only the intercepted call is recorded
442   - assert wrapper.called.once()
443   -
444   -Just like argument constraints, you can also use `where_args` - e.g:
445   -
446   - def second_arg_is_a_string(a, b):
447   - return isinstance(b, str)
448   -
449   - wrapper = mock_on(obj).do_something.where_args(second_arg_is_a_string).returning("STRING")
450   - mock_do_something = wrapper.raw
451   -
452   - assert mock_do_something(1) == 11
453   - assert mock_do_something(2) == 12
454   -
455   - # but if the arguments do match:
456   - assert mock_do_something('5') == "STRING"
457   -
458   -
459   -#### Post-checking
460   -Specifying your expectations before anything happens is sometimes not the best
461   -(or easiest) thing to do.
462   -
463   -It's possible to just inspect the state of a mock to see what's happened to it
464   -so far. `called` is almost identical to `is_expected`. Unlike an expectation
465   -object, The result of a `called` expression should be compared to `True` or
466   -`False` to check whether the expressed call(s) did indeed happen.
467   -
468   - self.assertTrue(mock().called.once().with_args('foo'))
469   - if not mock().called.once():
470   - assert False, "Things went bad!"
471   -
472   -But the most useful feature of of `called` is its ability to retrieve the calls
473   -that the mock has received. So in the following example:
474   -
475   - wrapper = mock()
476   - raw_mock = wrapper.raw
477   -
478   - raw_mock('a', b='foo')
479   - raw_mock('b')
480   - raw_mock(b='bar')
481   -
482   - >>> wrapper.called.thrice().get_calls()
483   - [(('a',), {'b': 'foo'}), ('b',), (None, {'b': 'bar'})]
484   -
485   -Note that where a call has no arguments or has no keyword-arguments, the
486   -first or second element (respectively) in the call tuple is None instead of an
487   -empty tuple or dict. This is mostly for readability, because there are already
488   -enough parentheses in the mix.
489   -
490   -**Note**: get_calls will fail if the assertions made after `called` are not met.
491   -e.g: if mock has been called once and you ask for
492   -`wrapper.called.twice().get_calls()`, then you'll get an AssertionError.
493   -
494   -If you're only expecting one call, you can use `get_args`:
495   -
496   - mock(b='bar')
497   - >>> wrapper.called.once().get_args()
498   -
499   -**Note** that `get_args` requires you to explicitly specify `once()`.
500   -
501   ----
502   -# Testing the mocktest library
503   -I use [nosetests](http://code.google.com/p/python-nose/), and just run it from
504   -the root directory. You probably should too!
505   -
506   -#Thanks
507   -[Michael Foord](http://www.voidspace.org.uk/python/mock.html)
1  VERSION
... ... @@ -0,0 +1 @@
  1 +0.5
196 conf.py
... ... @@ -0,0 +1,196 @@
  1 +# -*- coding: utf-8 -*-
  2 +#
  3 +# mocktest documentation build configuration file, created by
  4 +# sphinx-quickstart on Tue Dec 28 12:04:30 2010.
  5 +#
  6 +# This file is execfile()d with the current directory set to its containing dir.
  7 +#
  8 +# Note that not all possible configuration values are present in this
  9 +# autogenerated file.
  10 +#
  11 +# All configuration values have a default; values that are commented out
  12 +# serve to show the default.
  13 +
  14 +import sys, os
  15 +
  16 +# If extensions (or modules to document with autodoc) are in another directory,
  17 +# add these directories to sys.path here. If the directory is relative to the
  18 +# documentation root, use os.path.abspath to make it absolute, like shown here.
  19 +#sys.path.append(os.path.abspath('.'))
  20 +
  21 +# -- General configuration -----------------------------------------------------
  22 +
  23 +# Add any Sphinx extension module names here, as strings. They can be extensions
  24 +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
  25 +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.ifconfig']
  26 +
  27 +# Add any paths that contain templates here, relative to this directory.
  28 +templates_path = ['doc/templates']
  29 +
  30 +# The suffix of source filenames.
  31 +source_suffix = '.rst'
  32 +
  33 +# The encoding of source files.
  34 +#source_encoding = 'utf-8'
  35 +
  36 +# The master toctree document.
  37 +master_doc = 'doc/index'
  38 +
  39 +# General information about the project.
  40 +project = u'mocktest'
  41 +copyright = u'2010, Tim Cuthbertson'
  42 +
  43 +# The version info for the project you're documenting, acts as replacement for
  44 +# |version| and |release|, also used in various other places throughout the
  45 +# built documents.
  46 +#
  47 +# The short X.Y version.
  48 +version = '0.5'
  49 +# The full version, including alpha/beta/rc tags.
  50 +release = '0.5'
  51 +
  52 +autodoc_default_flags = ['members']
  53 +
  54 +# The language for content autogenerated by Sphinx. Refer to documentation
  55 +# for a list of supported languages.
  56 +#language = None
  57 +
  58 +# There are two options for replacing |today|: either, you set today to some
  59 +# non-false value, then it is used:
  60 +#today = ''
  61 +# Else, today_fmt is used as the format for a strftime call.
  62 +#today_fmt = '%B %d, %Y'
  63 +
  64 +# List of documents that shouldn't be included in the build.
  65 +#unused_docs = []
  66 +
  67 +# List of directories, relative to source directory, that shouldn't be searched
  68 +# for source files.
  69 +exclude_trees = ['doc/build']
  70 +
  71 +# The reST default role (used for this markup: `text`) to use for all documents.
  72 +#default_role = None
  73 +
  74 +# If true, '()' will be appended to :func: etc. cross-reference text.
  75 +#add_function_parentheses = True
  76 +
  77 +# If true, the current module name will be prepended to all description
  78 +# unit titles (such as .. function::).
  79 +#add_module_names = True
  80 +
  81 +# If true, sectionauthor and moduleauthor directives will be shown in the
  82 +# output. They are ignored by default.
  83 +#show_authors = False
  84 +
  85 +# The name of the Pygments (syntax highlighting) style to use.
  86 +pygments_style = 'sphinx'
  87 +
  88 +# A list of ignored prefixes for module index sorting.
  89 +#modindex_common_prefix = []
  90 +
  91 +
  92 +# -- Options for HTML output ---------------------------------------------------
  93 +
  94 +# The theme to use for HTML and HTML Help pages. Major themes that come with
  95 +# Sphinx are currently 'default' and 'sphinxdoc'.
  96 +html_theme = 'default'
  97 +
  98 +# Theme options are theme-specific and customize the look and feel of a theme
  99 +# further. For a list of options available for each theme, see the
  100 +# documentation.
  101 +#html_theme_options = {}
  102 +
  103 +# Add any paths that contain custom themes here, relative to this directory.
  104 +#html_theme_path = []
  105 +
  106 +# The name for this set of Sphinx documents. If None, it defaults to
  107 +# "<project> v<release> documentation".
  108 +#html_title = None
  109 +
  110 +# A shorter title for the navigation bar. Default is the same as html_title.
  111 +#html_short_title = None
  112 +
  113 +# The name of an image file (relative to this directory) to place at the top
  114 +# of the sidebar.
  115 +#html_logo = None
  116 +
  117 +# The name of an image file (within the static path) to use as favicon of the
  118 +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
  119 +# pixels large.
  120 +#html_favicon = None
  121 +
  122 +# Add any paths that contain custom static files (such as style sheets) here,
  123 +# relative to this directory. They are copied after the builtin static files,
  124 +# so a file named "default.css" will overwrite the builtin "default.css".
  125 +html_static_path = ['doc/static']
  126 +
  127 +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
  128 +# using the given strftime format.
  129 +#html_last_updated_fmt = '%b %d, %Y'
  130 +
  131 +# If true, SmartyPants will be used to convert quotes and dashes to
  132 +# typographically correct entities.
  133 +#html_use_smartypants = True
  134 +
  135 +# Custom sidebar templates, maps document names to template names.
  136 +#html_sidebars = {}
  137 +
  138 +# Additional templates that should be rendered to pages, maps page names to
  139 +# template names.
  140 +#html_additional_pages = {}
  141 +
  142 +# If false, no module index is generated.
  143 +#html_use_modindex = True
  144 +
  145 +# If false, no index is generated.
  146 +#html_use_index = True
  147 +
  148 +# If true, the index is split into individual pages for each letter.
  149 +#html_split_index = False
  150 +
  151 +# If true, links to the reST sources are added to the pages.
  152 +#html_show_sourcelink = True
  153 +
  154 +# If true, an OpenSearch description file will be output, and all pages will
  155 +# contain a <link> tag referring to it. The value of this option must be the
  156 +# base URL from which the finished HTML is served.
  157 +#html_use_opensearch = ''
  158 +
  159 +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
  160 +#html_file_suffix = ''
  161 +
  162 +# Output file base name for HTML help builder.
  163 +htmlhelp_basename = 'mocktestdoc'
  164 +
  165 +
  166 +# -- Options for LaTeX output --------------------------------------------------
  167 +
  168 +# The paper size ('letter' or 'a4').
  169 +#latex_paper_size = 'letter'
  170 +
  171 +# The font size ('10pt', '11pt' or '12pt').
  172 +#latex_font_size = '10pt'
  173 +
  174 +# Grouping the document tree into LaTeX files. List of tuples
  175 +# (source start file, target name, title, author, documentclass [howto/manual]).
  176 +latex_documents = [
  177 + ('index', 'mocktest.tex', u'mocktest Documentation',
  178 + u'Tim Cuthbertson', 'manual'),
  179 +]
  180 +
  181 +# The name of an image file (relative to this directory) to place at the top of
  182 +# the title page.
  183 +#latex_logo = None
  184 +
  185 +# For "manual" documents, if this is true, then toplevel headings are parts,
  186 +# not chapters.
  187 +#latex_use_parts = False
  188 +
  189 +# Additional stuff for the LaTeX preamble.
  190 +#latex_preamble = ''
  191 +
  192 +# Documents to append as an appendix to all manuals.
  193 +#latex_appendices = []
  194 +
  195 +# If false, no module index is generated.
  196 +#latex_use_modindex = True
238 doc/index.rst
Source Rendered
... ... @@ -0,0 +1,238 @@
  1 +mocktest
  2 +********
  3 +... is a powerful and easy-to-use mocking library, inspired by rspec and
  4 +similar in some ways to Michael Foord's popular Mock module.
  5 +
  6 +The main features are:
  7 +
  8 + - expressive DSL for specifying expectations, stubs and replacement objects
  9 + - powerful expectation matching behaviour for mock objects
  10 + - automatic verification of expectations (before each test's tearDown)
  11 + - automatic rollback of inserted mock objects after each test
  12 + - descriptive error messages when something fails
  13 +
  14 +
  15 +It's released under the BSD licence (see the LICENCE file).
  16 +
  17 +| Source / Readme / Issues:
  18 +| http://github.com/gfxmonk/mocktest/tree/master
  19 +
  20 +
  21 +| Cheese shop entry:
  22 +| http://pypi.python.org/pypi/mocktest
  23 +
  24 +
  25 +| Zero install feed:
  26 +| http://gfxmonk.net/dist/0install/mocktest.xml
  27 +
  28 +API reference
  29 +-----------------
  30 +
  31 +This document is an introduction, if you are looking for an API reference
  32 +you should read the :mod:`mocktest module documentation <mocktest>`.
  33 +
  34 +
  35 +Important notes for this version
  36 +--------------------------------
  37 +
  38 +Mocktest 0.5 is a fairly thorough rewrite. Most of the semantics and features
  39 +remain the same, but the implementation has been simplified. Some features are
  40 +no longer present, other (hopefully more useful) features have been added. I
  41 +apologise for those using mocktest <=0.3 - most of the features you use should
  42 +still work, they may just be written differently.
  43 +
  44 +Most importantly, there is no longer any distinction between a raw mock and a
  45 +mock wrapper. Instead, mock expectations are specified by using one of the
  46 +global functions - `expect` and `when`. The distinction turned out to be
  47 +confusing, and made many tests awkward.
  48 +
  49 +Where did it come from?
  50 +-----------------------
  51 +I am a big fan of rspec, but less of a fan of ruby as a whole.
  52 +I wanted a to use rspec's powerful `should_receive()` and associated matchers
  53 +with my python mock objects.
  54 +
  55 +mocktest is by no means a port of rspec - it is smaller and simpler, and a lot
  56 +more pythonic.
  57 +
  58 +what *are* mocks?
  59 +-----------------
  60 +
  61 +What are mocks used for? mocks can pretend to be pretty much any object. Mocks
  62 +record what happens to them (accessors, method calls, etc) and allow you to
  63 +verify that this is what you expected. Replace a database connection with a mock
  64 +and make sure the right commands are being sent to your database - without the
  65 +overhead and trouble of using an actual database. Replace os.system with a mock,
  66 +and supply your own response to shell commands. Mocks can be used to satisfy
  67 +dependencies or simulate external conditions in your program so you can focus
  68 +on unit-level testing.
  69 +
  70 +mocktest usage
  71 +**************
  72 +
  73 +When using mocktest, you should always use :class:`mocktest.TestCase` instead of
  74 +:class:`unittest.TestCase`. Mocktest's version is almost identical, but automatically
  75 +calls the required setup and teardown hooks for the mocktest library.
  76 +
  77 +If you wish to use mocks outside test cases, you can use the mock transaction
  78 +manager directly to handle these checks for you.
  79 +
  80 + >>> from mocktest import MockTransaction
  81 + >>> with MockTransaction:
  82 + ... # perform all your checks in here
  83 + ... # expectations will be verified once the indented block finishes
  84 +
  85 +Or, if you are playing around on the console, you can manually call
  86 +`MockTransaction.__enter__()` and `MockTransaction.__exit()` to start/end a
  87 +mock transaction.
  88 +
  89 +There is one important addition to the :class:`~mocktest.mocktest.TestCase` class:
  90 +
  91 +.. automethod:: mocktest.mocktest.TestCase.assertRaises
  92 +
  93 +This was adapted from http://code.activestate.com/recipes/307970/
  94 +
  95 +Creating mocks
  96 +--------------
  97 +
  98 +mocktest is still a young framework, and is likely to evolve. While the
  99 +inspiration is from rspec, a lot of the mechanics differ either necessarily
  100 +because of differences between ruby and python, or just to make things cleaner.
  101 +
  102 +One important part of mocking is test isolation - that is, changes you make in
  103 +one test for the sake of mocking should never be visible outside that test
  104 +case. Mocktest takes care of all that for you, even when you mock or replace
  105 +attributes on global objects.
  106 +
  107 +So, let's get started:
  108 +
  109 +If you want to replace a method on an existing object, you can use :func:`~mocktest.mocking.when`:
  110 +
  111 + >>> when(some_object).method.then_return(True)
  112 +
  113 +This will ensure that `some_object.method()` always returns True (and doesn't call
  114 +the previous implementation of `method`, if there is one). This action will
  115 +take place regardless of the arguments passed in to `method`.
  116 +
  117 +To only deal with some of the calls made to method, you can specify under which
  118 +conditions your action should occur by just passing those arguments when call the
  119 +:func:`~mocktest.mocking.when` function's `method`. For example:
  120 +
  121 + >>> when(some_object).method().then_return('no args')
  122 + >>> when(some_object).method(1, 2, 3).then_return('one two three')
  123 +
  124 +After this, you would see:
  125 +
  126 + >>> some_object.method()
  127 + 'no args'
  128 +
  129 + >>> some_object.method(1, 2, 3)
  130 + 'one two three'
  131 +
  132 + >>> some_object.method('unexpected arguments')
  133 + TypeError: stubbed method 'method' received unexpected arguments: ('unexpected arguments')
  134 + Allowable argument conditions are:
  135 + - arguments equal to: ()
  136 + - arguments equal to: (1, 2, 3)
  137 +
  138 +In order to make sure that the method call you want to happen actually does, you
  139 +can use :func:`~mocktest.mocking.expect`. :func:`~mocktest.mocking.expect`
  140 +is exactly like :func:`~mocktest.mocking.when`, except once the test is complete,
  141 +it makes sure the method you were expecting really was called.
  142 +
  143 +And finally, if you don't already have an object, you can quickly get one by calling
  144 +:func:`~mocktest.mocking.mock`:
  145 +
  146 + >>> obj = mock('my mock')
  147 +
  148 +Mock customisation
  149 +------------------
  150 +
  151 +A stubbed method has a number of options for specifying its behaviour including
  152 +return values and expectations. For the full API, see :ref:`setting-expectations`.
  153 +
  154 +The basic setup of a test case is identical to using unittest.TestCase:
  155 +
  156 + >>> from mocktest import *
  157 + >>> class MyTestClass(TestCase):
  158 + ... def setUp(self):
  159 + ... # common setup actions...
  160 + ...
  161 + ... def tearDown(self):
  162 + ... # common teardown actions...
  163 + ...
  164 + ... def test_feature_a(self):
  165 + ... #test the functionality in feature a
  166 + ...
  167 + ... def test_feature_b(self):
  168 + ... #test the functionality in feature b
  169 +
  170 +Expecting calls
  171 +^^^^^^^^^^^^^^^
  172 +
  173 + >>> expect(os).system
  174 +
  175 +This will fail your test unless os.system() is called at least once during
  176 +the current test case (the check is made right before the `tearDown()` method
  177 +is executed).
  178 +
  179 +Expecting Arguments
  180 +^^^^^^^^^^^^^^^^^^^
  181 +
  182 +| To specify what argument's you're expecting, just pass them in:
  183 +| `expect(obj).method(<args>)`
  184 +
  185 +e.g:
  186 +
  187 + >>> expect(obj).method(1, 2, 3)
  188 + >>> expect(obj).method(1, 2, 3, foo='bar').once()
  189 + >>> expect(obj).method()
  190 +
  191 +Argument Constraints
  192 +^^^^^^^^^^^^^^^^^^^^
  193 +
  194 +You don't have to pass in the exact arguments. You can use matchers, or even your own function:
  195 +
  196 + >>> expect(obj).method(any_string)
  197 + >>> expect(obj).method(not_(any_int), **kwargs_containing(x=1))
  198 + >>> expect(obj).method.where(lambda *a, **kw: len(a) + len(kw) == 3)
  199 +
  200 +.. comment to fix vim highlights**
  201 +
  202 +If you're going to use a checking function more than once, you should make a matcher.
  203 +You can either subclass :class:`~mocktest.matchers.base.Matcher`, or use
  204 +the utility :func:`~mocktest.matchers.base.matcher` function.
  205 +
  206 +Post-checking
  207 +^^^^^^^^^^^^^
  208 +Specifying your expectations before anything happens is sometimes not the best
  209 +(or easiest) thing to do.
  210 +
  211 +It's possible to just inspect the state of a stub or mock to see what's happened to it
  212 +so far. :data:`received_calls` provides access to the calls received so far. It is a
  213 +list of :class:`~mocktest.callrecord.Call` objects:
  214 +
  215 +For a mock:
  216 +
  217 + >>> mock.foo.bar()
  218 + >>> mock.foo.bar(1, 2, x=3)
  219 + >>> mock.foo.bar.received_calls
  220 + [<#Call: ((), {})>, <#Call: ((1, 2), {'x': 3})>]
  221 +
  222 +And for a stubbed method:
  223 +
  224 + >>> expect(foo).bar
  225 + >>> foo.bar(1, 2, x=3)
  226 + >>> foo.bar.received_calls
  227 + [<#Call: ((1, 2), {'x': 3})>]
  228 +
  229 +
  230 +Testing the mocktest library
  231 +----------------------------
  232 +I use `nosetests <http://code.google.com/p/python-nose/>`_, and just run it from
  233 +the root directory. You probably should too!
  234 +
  235 +Thanks
  236 +------
  237 +`Michael Foord <http://www.voidspace.org.uk/python/mock.html>`_
  238 +
7 doc/mocktest.rst
Source Rendered
... ... @@ -0,0 +1,7 @@
  1 +Mocktest module
  2 +**************************
  3 +**Note**: (all of these classes and methods are available from the toplevel `mocktest` module, despite the use of fully-qualified names here)
  4 +
  5 +.. automodule:: mocktest
  6 + :members:
  7 +
17 mocktest.xml
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" ?>
  2 +<?xml-stylesheet type='text/xsl' href='interface.xsl'?>
  3 +<interface uri="http://gfxmonk.net/dist/0install/mocktest.xml" xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  4 + <name>mocktest</name>
  5 + <summary>mocking library for python, inspired by rspec</summary>
  6 + <description>
  7 + </description>
  8 + <homepage>http://gfxmonk.net/dist/doc/mocktest/doc/</homepage>
  9 +
  10 + <group main="mocktest">
  11 + <implementation id="sha1new=4b4c1f56d53bb8f16ef6b182e7f6c90e62b3aae8" released="2010-12-28" version="0.5">
  12 +
  13 + <manifest-digest sha256="97baab0aaa7aff4758c2f7a45ffbe6c89d492b4dc2635feb7b33de9bb4f660c3"/>
  14 + <archive href="http://gfxmonk.net/dist/0install/mocktest/mocktest-0.5.tgz" size="43051"/>
  15 + </implementation>
  16 + </group>
  17 +</interface>
104 mocktest/__init__.py
... ... @@ -1,7 +1,107 @@
  1 +"""
  2 +.. automodule:: mocktest.mocktest
  3 + :members:
  4 +
  5 +.. automodule:: mocktest.mocking
  6 + :members:
  7 +
  8 +
  9 +.. _setting-expectations:
  10 +
  11 +Setting expectations
  12 +--------------------
  13 +
  14 +The return type from :func:`when` and :func:`expect` is of type MockAct.
  15 +
  16 +.. class:: mocktest.mocking.MockAct
  17 +
  18 + .. method:: __call__(*a, **kw)
  19 +
  20 + Set the conditions under which this act will apply. Arguments can
  21 + be normal objects (checked for equality), or :class:`Matcher` instances.
  22 +
  23 + .. method:: where(condition_func)
  24 +
  25 + Match only when `condition_func` returns true, when called with the same
  26 + arguments as this method.
  27 +
  28 + .. method:: exactly(number)
  29 +
  30 + Expect this act to be triggered exactly `number` times.
  31 + Usually followed by `times()` for readability, as in:
  32 + >>> expect(obj).meth.exactly(3).times()
  33 +
  34 + .. method:: at_least(number)
  35 +
  36 + Expect this act to match at least `number` times.
  37 +
  38 + .. method:: at_most(number)
  39 +
  40 + Expect this act to match at most `number` times.
  41 +
  42 + .. method:: between(lower, upper)
  43 +
  44 + Expect this act to match between `lower` and `upper` times.
  45 +
  46 + .. method:: never()
  47 +
  48 + Alias for exactly(0).times()
  49 +
  50 + .. method:: once()
  51 +
  52 + Alias for exactly(1).time()
  53 +
  54 + .. method:: twice()
  55 +
  56 + Alias for exactly(2).times()
  57 +
  58 + .. method:: thrice()
  59 +
  60 + Alias for exactly(3).times()
  61 +
  62 + .. method:: and_return(result)
  63 +
  64 + When this act matches, return the given `result` to the caller.
  65 +
  66 + .. method:: and_raise(exc)
  67 +
  68 + When this act matches, raise the given exception instance.
  69 +
  70 + .. method:: and_call(func)
  71 +
  72 + When this act matches, call the given `func` and return its value.
  73 +
  74 + **Note:** `and_raise`, `and_return` and `and_call` each have a `then_*` alias
  75 + for better readability when using `when`. e.g:
  76 +
  77 + >>> expect(obj).foo().and_return(True)
  78 +
  79 + Is readable, however when using `when`, the following is more readable:
  80 +
  81 + >>> when(obj).foo().then_return(True)
  82 +
  83 + Both `and_` and `then_` versions have the same effect however.
  84 +
  85 +
  86 +
  87 +
  88 +.. class mocktest.mocking.StubbedMethod
  89 +This is the type that mocktest uses as a stand-in for a replaced (stubbed) method. For example:
  90 + >>> when(obj).method().then_return(True)
  91 + :members:
  92 +
  93 +.. automodule:: mocktest.transaction
  94 + :members:
  95 +
  96 +.. automodule:: mocktest.matchers
  97 + :members:
  98 +
  99 +.. automodule:: mocktest.callrecord
  100 + :members:
  101 +
  102 +"""
1 103 from core import *
2 104 from mocktest import *
3 105 from mocking import *
4 106 from matchers import *
5 107 from callrecord import *
6   -
7   -__version__ = '0.3.0'
29 mocktest/callrecord.py
... ... @@ -1,8 +1,28 @@
  1 +"""
  2 +Call Records
  3 +------------
  4 +"""
1 5 import sys, traceback, os