зеркало из https://github.com/mozilla/gecko-dev.git
412 строки
13 KiB
Plaintext
412 строки
13 KiB
Plaintext
====================================
|
|
Mock - Mocking and Testing Library
|
|
====================================
|
|
|
|
.. currentmodule:: mock
|
|
|
|
:Author: `Michael Foord
|
|
<http://www.voidspace.org.uk/python/weblog/index.shtml>`_
|
|
:Version: |release|
|
|
:Date: 2012/10/07
|
|
:Homepage: `Mock Homepage`_
|
|
:Download: `Mock on PyPI`_
|
|
:Documentation: `PDF Documentation
|
|
<http://www.voidspace.org.uk/downloads/mock-1.0.0.pdf>`_
|
|
:License: `BSD License`_
|
|
:Support: `Mailing list (testing-in-python@lists.idyll.org)
|
|
<http://lists.idyll.org/listinfo/testing-in-python>`_
|
|
:Issue tracker: `Google code project
|
|
<http://code.google.com/p/mock/issues/list>`_
|
|
|
|
.. _Mock Homepage: http://www.voidspace.org.uk/python/mock/
|
|
.. _BSD License: http://www.voidspace.org.uk/python/license.shtml
|
|
|
|
|
|
.. currentmodule:: mock
|
|
|
|
.. module:: mock
|
|
:synopsis: Mock object and testing library.
|
|
|
|
.. index:: introduction
|
|
|
|
mock is a library for testing in Python. It allows you to replace parts of
|
|
your system under test with mock objects and make assertions about how they
|
|
have been used.
|
|
|
|
mock is now part of the Python standard library, available as `unittest.mock
|
|
<http://docs.python.org/py3k/library/unittest.mock.html#module-unittest.mock>`_
|
|
in Python 3.3 onwards.
|
|
|
|
mock provides a core :class:`Mock` class removing the need to create a host
|
|
of stubs throughout your test suite. After performing an action, you can make
|
|
assertions about which methods / attributes were used and arguments they were
|
|
called with. You can also specify return values and set needed attributes in
|
|
the normal way.
|
|
|
|
Additionally, mock provides a :func:`patch` decorator that handles patching
|
|
module and class level attributes within the scope of a test, along with
|
|
:const:`sentinel` for creating unique objects. See the `quick guide`_ for
|
|
some examples of how to use :class:`Mock`, :class:`MagicMock` and
|
|
:func:`patch`.
|
|
|
|
Mock is very easy to use and is designed for use with
|
|
`unittest <http://pypi.python.org/pypi/unittest2>`_. Mock is based on
|
|
the 'action -> assertion' pattern instead of `'record -> replay'` used by many
|
|
mocking frameworks.
|
|
|
|
mock is tested on Python versions 2.4-2.7, Python 3 plus the latest versions of
|
|
Jython and PyPy.
|
|
|
|
|
|
.. testsetup::
|
|
|
|
class ProductionClass(object):
|
|
def method(self, *args):
|
|
pass
|
|
|
|
module = sys.modules['module'] = ProductionClass
|
|
ProductionClass.ClassName1 = ProductionClass
|
|
ProductionClass.ClassName2 = ProductionClass
|
|
|
|
|
|
|
|
API Documentation
|
|
=================
|
|
|
|
.. toctree::
|
|
:maxdepth: 2
|
|
|
|
mock
|
|
patch
|
|
helpers
|
|
sentinel
|
|
magicmock
|
|
|
|
|
|
User Guide
|
|
==========
|
|
|
|
.. toctree::
|
|
:maxdepth: 2
|
|
|
|
getting-started
|
|
examples
|
|
compare
|
|
changelog
|
|
|
|
|
|
.. index:: installing
|
|
|
|
Installing
|
|
==========
|
|
|
|
The current version is |release|. Mock is stable and widely used. If you do
|
|
find any bugs, or have suggestions for improvements / extensions
|
|
then please contact us.
|
|
|
|
* `mock on PyPI <http://pypi.python.org/pypi/mock>`_
|
|
* `mock documentation as PDF
|
|
<http://www.voidspace.org.uk/downloads/mock-1.0.0.pdf>`_
|
|
* `Google Code Home & Mercurial Repository <http://code.google.com/p/mock/>`_
|
|
|
|
.. index:: repository
|
|
.. index:: hg
|
|
|
|
You can checkout the latest development version from the Google Code Mercurial
|
|
repository with the following command:
|
|
|
|
``hg clone https://mock.googlecode.com/hg/ mock``
|
|
|
|
|
|
.. index:: pip
|
|
.. index:: easy_install
|
|
.. index:: setuptools
|
|
|
|
If you have pip, setuptools or distribute you can install mock with:
|
|
|
|
| ``easy_install -U mock``
|
|
| ``pip install -U mock``
|
|
|
|
Alternatively you can download the mock distribution from PyPI and after
|
|
unpacking run:
|
|
|
|
``python setup.py install``
|
|
|
|
|
|
Quick Guide
|
|
===========
|
|
|
|
:class:`Mock` and :class:`MagicMock` objects create all attributes and
|
|
methods as you access them and store details of how they have been used. You
|
|
can configure them, to specify return values or limit what attributes are
|
|
available, and then make assertions about how they have been used:
|
|
|
|
.. doctest::
|
|
|
|
>>> from mock import MagicMock
|
|
>>> thing = ProductionClass()
|
|
>>> thing.method = MagicMock(return_value=3)
|
|
>>> thing.method(3, 4, 5, key='value')
|
|
3
|
|
>>> thing.method.assert_called_with(3, 4, 5, key='value')
|
|
|
|
:attr:`side_effect` allows you to perform side effects, including raising an
|
|
exception when a mock is called:
|
|
|
|
.. doctest::
|
|
|
|
>>> mock = Mock(side_effect=KeyError('foo'))
|
|
>>> mock()
|
|
Traceback (most recent call last):
|
|
...
|
|
KeyError: 'foo'
|
|
|
|
>>> values = {'a': 1, 'b': 2, 'c': 3}
|
|
>>> def side_effect(arg):
|
|
... return values[arg]
|
|
...
|
|
>>> mock.side_effect = side_effect
|
|
>>> mock('a'), mock('b'), mock('c')
|
|
(1, 2, 3)
|
|
>>> mock.side_effect = [5, 4, 3, 2, 1]
|
|
>>> mock(), mock(), mock()
|
|
(5, 4, 3)
|
|
|
|
Mock has many other ways you can configure it and control its behaviour. For
|
|
example the `spec` argument configures the mock to take its specification
|
|
from another object. Attempting to access attributes or methods on the mock
|
|
that don't exist on the spec will fail with an `AttributeError`.
|
|
|
|
The :func:`patch` decorator / context manager makes it easy to mock classes or
|
|
objects in a module under test. The object you specify will be replaced with a
|
|
mock (or other object) during the test and restored when the test ends:
|
|
|
|
.. doctest::
|
|
|
|
>>> from mock import patch
|
|
>>> @patch('module.ClassName2')
|
|
... @patch('module.ClassName1')
|
|
... def test(MockClass1, MockClass2):
|
|
... module.ClassName1()
|
|
... module.ClassName2()
|
|
|
|
... assert MockClass1 is module.ClassName1
|
|
... assert MockClass2 is module.ClassName2
|
|
... assert MockClass1.called
|
|
... assert MockClass2.called
|
|
...
|
|
>>> test()
|
|
|
|
.. note::
|
|
|
|
When you nest patch decorators the mocks are passed in to the decorated
|
|
function in the same order they applied (the normal *python* order that
|
|
decorators are applied). This means from the bottom up, so in the example
|
|
above the mock for `module.ClassName1` is passed in first.
|
|
|
|
With `patch` it matters that you patch objects in the namespace where they
|
|
are looked up. This is normally straightforward, but for a quick guide
|
|
read :ref:`where to patch <where-to-patch>`.
|
|
|
|
As well as a decorator `patch` can be used as a context manager in a with
|
|
statement:
|
|
|
|
.. doctest::
|
|
|
|
>>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
|
|
... thing = ProductionClass()
|
|
... thing.method(1, 2, 3)
|
|
...
|
|
>>> mock_method.assert_called_once_with(1, 2, 3)
|
|
|
|
|
|
There is also :func:`patch.dict` for setting values in a dictionary just
|
|
during a scope and restoring the dictionary to its original state when the test
|
|
ends:
|
|
|
|
.. doctest::
|
|
|
|
>>> foo = {'key': 'value'}
|
|
>>> original = foo.copy()
|
|
>>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):
|
|
... assert foo == {'newkey': 'newvalue'}
|
|
...
|
|
>>> assert foo == original
|
|
|
|
Mock supports the mocking of Python :ref:`magic methods <magic-methods>`. The
|
|
easiest way of using magic methods is with the :class:`MagicMock` class. It
|
|
allows you to do things like:
|
|
|
|
.. doctest::
|
|
|
|
>>> mock = MagicMock()
|
|
>>> mock.__str__.return_value = 'foobarbaz'
|
|
>>> str(mock)
|
|
'foobarbaz'
|
|
>>> mock.__str__.assert_called_with()
|
|
|
|
Mock allows you to assign functions (or other Mock instances) to magic methods
|
|
and they will be called appropriately. The `MagicMock` class is just a Mock
|
|
variant that has all of the magic methods pre-created for you (well, all the
|
|
useful ones anyway).
|
|
|
|
The following is an example of using magic methods with the ordinary Mock
|
|
class:
|
|
|
|
.. doctest::
|
|
|
|
>>> mock = Mock()
|
|
>>> mock.__str__ = Mock(return_value='wheeeeee')
|
|
>>> str(mock)
|
|
'wheeeeee'
|
|
|
|
For ensuring that the mock objects in your tests have the same api as the
|
|
objects they are replacing, you can use :ref:`auto-speccing <auto-speccing>`.
|
|
Auto-speccing can be done through the `autospec` argument to patch, or the
|
|
:func:`create_autospec` function. Auto-speccing creates mock objects that
|
|
have the same attributes and methods as the objects they are replacing, and
|
|
any functions and methods (including constructors) have the same call
|
|
signature as the real object.
|
|
|
|
This ensures that your mocks will fail in the same way as your production
|
|
code if they are used incorrectly:
|
|
|
|
.. doctest::
|
|
|
|
>>> from mock import create_autospec
|
|
>>> def function(a, b, c):
|
|
... pass
|
|
...
|
|
>>> mock_function = create_autospec(function, return_value='fishy')
|
|
>>> mock_function(1, 2, 3)
|
|
'fishy'
|
|
>>> mock_function.assert_called_once_with(1, 2, 3)
|
|
>>> mock_function('wrong arguments')
|
|
Traceback (most recent call last):
|
|
...
|
|
TypeError: <lambda>() takes exactly 3 arguments (1 given)
|
|
|
|
`create_autospec` can also be used on classes, where it copies the signature of
|
|
the `__init__` method, and on callable objects where it copies the signature of
|
|
the `__call__` method.
|
|
|
|
|
|
.. index:: references
|
|
.. index:: articles
|
|
|
|
References
|
|
==========
|
|
|
|
Articles, blog entries and other stuff related to testing with Mock:
|
|
|
|
* `Imposing a No DB Discipline on Django unit tests
|
|
<https://github.com/carljm/django-testing-slides/blob/master/models/30_no_database.md>`_
|
|
* `mock-django: tools for mocking the Django ORM and models
|
|
<https://github.com/dcramer/mock-django>`_
|
|
* `PyCon 2011 Video: Testing with mock <https://blip.tv/file/4881513>`_
|
|
* `Mock objects in Python
|
|
<http://noopenblockers.com/2012/01/06/mock-objects-in-python/>`_
|
|
* `Python: Injecting Mock Objects for Powerful Testing
|
|
<http://blueprintforge.com/blog/2012/01/08/python-injecting-mock-objects-for-powerful-testing/>`_
|
|
* `Python Mock: How to assert a substring of logger output
|
|
<http://www.michaelpollmeier.com/python-mock-how-to-assert-a-substring-of-logger-output/>`_
|
|
* `Mocking Django <http://www.mattjmorrison.com/2011/09/mocking-django.html>`_
|
|
* `Mocking dates and other classes that can't be modified
|
|
<http://williamjohnbert.com/2011/07/how-to-unit-testing-in-django-with-mocking-and-patching/>`_
|
|
* `Mock recipes <http://konryd.blogspot.com/2010/06/mock-recipies.html>`_
|
|
* `Mockity mock mock - some love for the mock module
|
|
<http://konryd.blogspot.com/2010/05/mockity-mock-mock-some-love-for-mock.html>`_
|
|
* `Coverage and Mock (with django)
|
|
<http://mattsnider.com/python/mock-and-coverage/>`_
|
|
* `Python Unit Testing with Mock <http://www.insomnihack.com/?p=194>`_
|
|
* `Getting started with Python Mock
|
|
<http://myadventuresincoding.wordpress.com/2011/02/26/python-python-mock-cheat-sheet/>`_
|
|
* `Smart Parameter Checks with mock
|
|
<http://tobyho.com/2011/03/24/smart-parameter-checks-in/>`_
|
|
* `Python mock testing techniques and tools
|
|
<http://agiletesting.blogspot.com/2009/07/python-mock-testing-techniques-and.html>`_
|
|
* `How To Test Django Template Tags
|
|
<http://techblog.ironfroggy.com/2008/10/how-to-test.html>`_
|
|
* `A presentation on Unit Testing with Mock
|
|
<http://pypap.blogspot.com/2008/10/newbie-nugget-unit-testing-with-mock.html>`_
|
|
* `Mocking with Django and Google AppEngine
|
|
<http://michael-a-nelson.blogspot.com/2008/09/mocking-with-django-and-google-app.html>`_
|
|
|
|
|
|
.. index:: tests
|
|
.. index:: unittest2
|
|
|
|
Tests
|
|
=====
|
|
|
|
Mock uses `unittest2 <http://pypi.python.org/pypi/unittest2>`_ for its own
|
|
test suite. In order to run it, use the `unit2` script that comes with
|
|
`unittest2` module on a checkout of the source repository:
|
|
|
|
`unit2 discover`
|
|
|
|
If you have `setuptools <http://pypi.python.org/pypi/distribute>`_ as well as
|
|
unittest2 you can run:
|
|
|
|
``python setup.py test``
|
|
|
|
On Python 3.2 you can use ``unittest`` module from the standard library.
|
|
|
|
``python3.2 -m unittest discover``
|
|
|
|
.. index:: Python 3
|
|
|
|
On Python 3 the tests for unicode are skipped as they are not relevant. On
|
|
Python 2.4 tests that use the with statements are skipped as the with statement
|
|
is invalid syntax on Python 2.4.
|
|
|
|
|
|
.. index:: older versions
|
|
|
|
Older Versions
|
|
==============
|
|
|
|
Documentation for older versions of mock:
|
|
|
|
* `mock 0.8 <http://www.voidspace.org.uk/python/mock/0.8/>`_
|
|
* `mock 0.7 <http://www.voidspace.org.uk/python/mock/0.7/>`_
|
|
* `mock 0.6 <http://www.voidspace.org.uk/python/mock/0.6.0/>`_
|
|
|
|
Docs from the in-development version of `mock` can be found at
|
|
`mock.readthedocs.org <http://mock.readthedocs.org>`_.
|
|
|
|
|
|
Terminology
|
|
===========
|
|
|
|
Terminology for objects used to replace other ones can be confusing. Terms
|
|
like double, fake, mock, stub, and spy are all used with varying meanings.
|
|
|
|
In `classic mock terminology
|
|
<http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html>`_
|
|
:class:`mock.Mock` is a `spy <http://xunitpatterns.com/Test%20Spy.html>`_ that
|
|
allows for *post-mortem* examination. This is what I call the "action ->
|
|
assertion" [#]_ pattern of testing.
|
|
|
|
I'm not however a fan of this "statically typed mocking terminology"
|
|
promulgated by `Martin Fowler
|
|
<http://martinfowler.com/articles/mocksArentStubs.html>`_. It confuses usage
|
|
patterns with implementation and prevents you from using natural terminology
|
|
when discussing mocking.
|
|
|
|
I much prefer duck typing, if an object used in your test suite looks like a
|
|
mock object and quacks like a mock object then it's fine to call it a mock, no
|
|
matter what the implementation looks like.
|
|
|
|
This terminology is perhaps more useful in less capable languages where
|
|
different usage patterns will *require* different implementations.
|
|
`mock.Mock()` is capable of being used in most of the different roles
|
|
described by Fowler, except (annoyingly / frustratingly / ironically) a Mock
|
|
itself!
|
|
|
|
How about a simpler definition: a "mock object" is an object used to replace a
|
|
real one in a system under test.
|
|
|
|
.. [#] This pattern is called "AAA" by some members of the testing community;
|
|
"Arrange - Act - Assert".
|