pymockobject 0.5
Mock Object library
pymockobject - A Mock object library for Python.
==================================
Introduction
----------
pymockobject is mockobject library, designed to be used by unit tests written
in Python.
Mock objects are typically employed in a unittest when a dependacy of the class
under test needs to access an external, or expensive-to-access resource.
Another usage case is to reduce the number of dependancies in tests.
In both of these scenarios, when the interface of the object class that the
mock object replaces in test changes, it is desirable that we don't have to
go around changing the mock object definitions we created in the tests.
Motivation
---------
A few mock object frameworks are availbale for python, so why create another?
- Mock objects should not be created unless they match the type they are
mocking in terms of method signatures.
That is, if the object you are mocking 'Foo', has a method 'bar' defined as:
def bar(self, a, b, c=None):
.....
Then a call to such as :
mock.bar(1,2,3, d=4)
should fail, since the real 'bar' method does not take a keyword parameter 'd'.
- Mock objects should be a subclass of the target subject
- This permits code which uses type-checking via isinstance, cmp, eq and friends
to work with mock objects.
- A mock object's method should respond to messages, rather than passing a message
to the mock object along with a string identifying the method (usually by name).
I considered:
mock.foo()
mock.assert_called("foo", *with_args, **with_kwargs)
vs.
mock.foo()
mock.foo.assert_called(*with_args, **with_kwargs)
and concluded I prefer the later (which is the current implementation).
Whilst this could be seen as a style preferance, I believe accessing the method
as an attribute to be (arguably) more readable, but more importantly more
transparent as to what's going on. It is the method's state which we are interested
in most cases; The only requests that we ask commonly of the mock object itself
is to enumerate an ordered list of all the calls that have been made on it, or
to ask for all calls made on it of a give name.
Aims
----
- Produce more concise unit test code, by having less user defined mock objects
in scope.
- Hopefully, as a side effect of this, more readable tests.
- Reduce the amount of maintainance require to maintain tests as class interfaces
change. By insisting on creating a mock with the target type, there should be no
need to update the tests each time a developer decides to rename a method.
- This should hopefully reduce the lifecycle time of writing tests as consequence.
- Allow the use of mock objects in tests where it has before not possible due to type
checking (via isinstance or otherwise).
Features
-------
- Ensures that the methods mocked match the signatures of the subject.
i.e it is not possible to create a mock method 'foo' of object 'spam'
if 'foo' is not a named member of spam.__class__
- Ability to inspect the state of mock calls
- Installed as a python package
- Ability to specifiy pre and post call expectations for mock methods
- Supports installation as python eggs.
See INSTALL for details.
- Comprehensive documentation and tests provided,
For the main doctests, look at: pymockobject/__init__.py
All unittests for pymockobject live in the 'tests' sub-package.
Outstanding design questions
------------------------
- Should "Anonymous" mock object's be supported?
- An anonymous mock is a mock object that does not claim to be of any
specific type, instead it responds to any message (known as a "Tracer Buillet"),
A tracer buillet can be used in a program, and later inspected to find out which
methods have been called, how the program attempted to alter its state.
In my opinion, this is not a mock object, but a variation of a tracer butllet[1].
Mock objects, should as their name inferrs, simulate the type of the object
that will be passed to the code under test under production circumstances.
Where polymorphism applies, and the object may vary according to an interface or
base class, i propose that the unittest should employ a test that creates a mock
object for each of the variations, where applicable.
Should anyone have any compelling reasons why the above doesn't hold true,
please let me know of any use cases and I'll try to address them.
My assertions about anonymous mocks are purely driven from practical
experience.
- Should 'partial' mock objects be supported?
- A partial mock is a mock object that by default delgates to the instance of the
the type mocked - i.e calls the real code by default.
The idea is that one can mock out parts of the object under test, but allow the
the rest of the object to function as if it were the real thing.
Initially I thought this would be a cool feature to have, but after some thought, and
reading (www.mockobjects.com and others), I decided that I agreed with thathe
assertions others have made, if you find yourself wanting to mock out part of an
object, then that object is usually too large and can be decomposed into smaller
well defined compontents.
Todo
----
- Support any Python method type [?]
Ideally, any method type, including slot wrappers, builtin-methods
should be supported, unfortunatly, when mocking builtin types (dict, list, et al)
it is not currently possible (in Python 2.4.3) to inspect the argument
specification of methods, which are
defined of these types (they are of the types "method_descriptor", "slot_wrapper",
"builtin_function_or_method". This is because these methods are defined in C,
and the current Python C API does not expose a mechanism to retrieve method
arguments. This also means that descriptor methods such as
__str__, __repr__, __eq___ et al cannot be mocked (these are of the type
'method_descriptor', and these cannot be mocked, however, this will not cause
pymockobject to fail, instead it detects these method types and ignores them.
Mocking builtin objects is still supported, since it can be still useful for
other mock object features (expectations, call inspection).
The details of how the current implementation decides whether an instance's method
can be mocked can by found by reading the function:
pymockobject.reflect.get_methods
Known Bugs
----------
--------------------------------------------
If you find some or all of this module useful, please
donate a small amount to the Free Software Foundation,
Thanks!
| File | Type | Py Version | Size | # downloads |
|---|---|---|---|---|
| pymockobject-0.5-py2.4.egg (md5) | Python Egg | 2.4 | 86KB | 290 |
| pymockobject-0.5.tar.gz (md5) | Source | 24KB | 166 | |
- Author: Matthew Russell <horizon5 at users sourceforge net>
- Home Page: http://pymockobject.sourceforge.net/
- Download URL: http://cheeseshop.python.org/pypi/pymockobject/
- Keywords: mock object unit tests assertions xp
- License: GPL
- Platform: Any
- Categories
- Package Index Owner: matthewrussell
- DOAP record: pymockobject-0.5.xml
