Python Programming, news on the Voidspace Python Projects and all things techie.

mock 0.8 released

emoticon:film After more than six months development work mock 0.8 has been released. 0.8 is a big release with many new features, general improvements and bugfixes.

You can download mock 0.8.0 final from the PyPI page or install it with:

pip install -U mock

mock is a library for testing in Python. It allows you to replace parts of your system under test with mock objects.

The only changes in mock 0.8.0 final since 0.8rc2 are:

  • Improved repr of sentinel objects
  • ANY can be used for comparisons against call objects
  • The return value of MagicMock.__iter__ can be set to any iterable and isn't required to be an iterator

The full changelog since 0.7.2 is pretty large. Hopefully I'll do a series of blog posts explaining the major new features and how to use them. Several common patterns of testing with mock have become simpler in 0.8.

Several of the changes, particularly the improved reprs and error messages, come for free without you having to know anything about the other new features. For documentation on the new features, browse the links in the changelog.

Here's a brief example of the improved reprs / failure messages you get with mock 0.8:

>>> from mock import MagicMock
>>> m = MagicMock(name='foo')
>>> m.method(1, 2, 3).attribute['foo']
<MagicMock name='foo.method().attribute.__getitem__()' id='4300665616'>
>>> m.method.call_args
call(1, 2, 3)
>>> m.method.assert_called_with('some args')
Traceback (most recent call last):
  ...
AssertionError: Expected call: method('some args')
Actual call: method(1, 2, 3)

One of the best new features, for making assertions about several calls at once, is mock_calls in conjunction with the call object:

>>> from mock import MagicMock, call
>>> m = MagicMock(name='foo')
>>> config = {'method.return_value.chained.return_value.nested.return_value': 3}
>>> m.configure_mock(**config)
>>> m.method('arg').chained().nested('call')
3
>>> m.mock_calls
[call.method('arg'),
 call.method().chained(),
 call.method().chained().nested('call')]
>>> m.mock_calls == [call.method('arg'),
...  call.method().chained(),
...  call.method().chained().nested('call')]
True
>>> expected_calls = call.method('arg').chained().nested('call').call_list()
>>> m.mock_calls == expected_calls
True

If you're still using mock 0.7, and can't upgrade all your test code yet, the 0.7 documentation is available online here.

The full List of changes since 0.7:

mock 0.8.0 is the last version that will support Python 2.4.

  • Addition of mock_calls list for all calls (including magic methods and chained calls)
  • patch and patch.object now create a MagicMock instead of a Mock by default
  • The patchers (patch, patch.object and patch.dict), plus Mock and MagicMock, take arbitrary keyword arguments for configuration
  • New mock method configure_mock for setting attributes and return values / side effects on the mock and its attributes
  • New mock assert methods assert_any_call and assert_has_calls
  • Implemented auto-speccing (recursive, lazy speccing of mocks with mocked signatures for functions/methods), as the autospec argument to patch
  • Added the create_autospec function for manually creating 'auto-specced' mocks
  • patch.multiple for doing multiple patches in a single call, using keyword arguments
  • Setting side_effect to an iterable will cause calls to the mock to return the next value from the iterable
  • New new_callable argument to patch and patch.object allowing you to pass in a class or callable object (instead of MagicMock) that will be called to replace the object being patched
  • Addition of NonCallableMock and NonCallableMagicMock, mocks without a __call__ method
  • Addition of mock_add_spec method for adding (or changing) a spec on an existing mock
  • Protocol methods on MagicMock are magic mocks, and are created lazily on first lookup. This means the result of calling a protocol method is a MagicMock instead of a Mock as it was previously
  • Addition of attach_mock method
  • Added ANY for ignoring arguments in assert_called_with calls
  • Addition of call helper object
  • Improved repr for mocks
  • Improved repr for call_args and entries in call_args_list, method_calls and mock_calls
  • Improved repr for sentinel objects
  • patch lookup is done at use time not at decoration time
  • In Python 2.6 or more recent, dir on a mock will report all the dynamically created attributes (or the full list of attributes if there is a spec) as well as all the mock methods and attributes.
  • Module level FILTER_DIR added to control whether dir(mock) filters private attributes. True by default.
  • patch.TEST_PREFIX for controlling how patchers recognise test methods when used to decorate a class
  • Support for using Java exceptions as a side_effect on Jython
  • Mock call lists (call_args_list, method_calls & mock_calls) are now custom list objects that allow membership tests for "sub lists" and have a nicer representation if you str or print them
  • Mocks attached as attributes or return values to other mocks have calls recorded in method_calls and mock_calls of the parent (unless a name is already set on the child)
  • Improved failure messages for assert_called_with and assert_called_once_with
  • The return value of the MagicMock.__iter__ method can be set to any iterable and isn't required to be an iterator
  • Added the Mock API (assert_called_with etc) to functions created by mocksignature
  • Tuples as well as lists can be used to specify allowed methods for spec & spec_set arguments
  • Calling stop on an unstarted patcher fails with a more meaningful error message
  • Renamed the internal classes Sentinel and SentinelObject to prevent abuse
  • BUGFIX: an error creating a patch, with nested patch decorators, won't leave patches in place
  • BUGFIX: __truediv__ and __rtruediv__ not available as magic methods on mocks in Python 3
  • BUGFIX: assert_called_with / assert_called_once_with can be used with self as a keyword argument
  • BUGFIX: when patching a class with an explicit spec / spec_set (not a boolean) it applies "spec inheritance" to the return value of the created mock (the "instance")
  • BUGFIX: remove the __unittest marker causing traceback truncation
  • Removal of deprecated patch_object
  • Private attributes _name, _methods, '_children', _wraps and _parent (etc) renamed to reduce likelihood of clash with user attributes.
  • Added license file to the distribution

Thanks to all those who suggested features, provided patches and helped test the mock 0.8 release. There are still plenty of ways mock can continue to improve, you can browse the issues list to get an idea of some of the outstanding feature requests and suggestions.

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2012-02-16 12:56:14 | |

Categories: , Tags: , ,


Hosted by Webfaction

Counter...