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

Mock 0.7.0 beta 4 Released

emoticon:exclaim mock is a Python library for simple mocking and patching (replacing objects with mocks during test runs). The "headline features" in 0.7.0 are Python 3 support and the ability to mock magic methods. You can now mock objects that behave like containers or are used as context managers. mock is designed for use with unittest, based on the action -> assertion pattern rather than record -> replay. People are happily using mock with Python test frameworks like nose and py.test.

0.7.0 is a major new release with a bunch of other new features and bugfixes as well.

The latest beta is now up on PyPI. 0.7.0 beta 4 is intended to be the last release before 0.7.0 final (read my lips - no new features), so please try it out and report any issues.

The work remaining before the final release is updating the documentation, especially the examples, to include the new features.

Changes since beta 3 are:

  • patchers (patch, patch.object and patch.dict) have start and stop methods
  • Addition of assert_called_once_with method
  • repr of a mock with a spec includes the class name of the spec
  • assert_called_with works with python -OO
  • New spec_set keyword argument to Mock and patch. If this is set, attempting to set an attribute on a mock not on the spec will raise an AttributeError
  • Attributes and return value of a MagicMock are MagicMock objects
  • Attempting to set an unsupported magic method now raises an AttributeError
  • patch.dict works as a class decorator
  • Switched from subversion to mercurial for source code control
  • BUGFIX: mocks are now copyable (thanks to Ned Batchelder for reporting and diagnosing this)
  • BUGFIX: spec=True works with old style classes
  • BUGFIX: mocksignature=True can now patch instance methods via patch.object

Although a tiny feature, of particular note is the addition of start and stop methods to patch objects. This is useful where you are doing the same patching on a whole bunch of test methods - it allows you to move the patching into your setUp and tearDown methods. (In 0.7.0 you can also use patch as a class decorator, which has a similar effect but requires Python 2.6):

from mock import patch
import unittest2 as unittest

class MyTest(unittest.TestCase):
    def setUp(self):
        self.patcher = patch('mymodule.foo')
        self.mock_foo = self.patcher.start()

    def tearDown(self):
        self.patcher.stop()

If you use this technique you must ensure that the patching is "undone" by calling stop. This can be fiddlier than you might think, because if an exception is raised in the setUp then tearDown is not called. unittest2 cleanup functions make this easier:

from mock import patch
import unittest2 as unittest

class MyTest(unittest.TestCase):
    def setUp(self):
        patcher = patch('mymodule.foo')
        self.addCleanup(patcher.stop)

        self.mock_foo = patcher.start()

In fact start and stop are just aliases for the context manager __enter__ and __exit__ methods, but calling them directly is ugly. Smile

For 0.8.0 we will look at a better way of managing multiple patches, but this is a good stopgap.

The full changelog for mock 0.7.0 (since 0.6.0) is:

  • Python 3 compatibility (tested with 3.2 but should work with 3.0 & 3.1 as well)
  • Ability to mock magic methods with Mock and addition of MagicMock with pre-created magic methods
  • Addition of mocksignature
  • Addition of mocksignature argument to patch and patch.object
  • Addition of patch.dict for changing dictionaries during a test
  • Ability to use patch, patch.object and patch.dict as class decorators
  • Renamed patch_object to patch.object (patch_object is deprecated)
  • Addition of soft comparisons: call_args, call_args_list and method_calls now return tuple-like objects which compare equal even when empty args or kwargs are skipped
  • patchers (patch, patch.object and patch.dict) have start and stop methods
  • Addition of assert_called_once_with method
  • Mocks can now be named (name argument to constructor) and the name is used in the repr
  • repr of a mock with a spec includes the class name of the spec
  • assert_called_with works with python -OO
  • New spec_set keyword argument to Mock and patch. If this is set, attempting to set an attribute on a mock not on the spec will raise an AttributeError
  • Mocks created with a spec can now pass isinstance tests (__class__ returns the type of the spec)
  • Improved failure message for Mock.assert_called_with when the mock has not been called at all
  • BUGFIX: mocks are now copyable (thanks to Ned Batchelder for reporting and diagnosing this)
  • BUGFIX: spec=True works with old style classes
  • BUGFIX: help(mock) works now (on the module). Can no longer use __bases__ as a valid sentinel name (thanks to Stephen Emslie for reporting and diagnosing this)
  • BUGFIX: side_effect now works with BaseException exceptions like KeyboardInterrupt
  • BUGFIX: patching the same object twice now restores the patches correctly
  • with statement tests now skipped on Python 2.4
  • Tests require unittest2 to run
  • Improved several docstrings and documentation
  • Added 'build_sphinx' command to setup.py (requires setuptools or distribute) Thanks to Florian Bauer
  • Switched from subversion to mercurial for source code control
  • Konrad Delong added as co-maintainer

As always, thanks to those of you who reported bugs or provided feeback, feature requests and patches!

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

Posted by Fuzzyman on 2010-11-16 11:53:12 | |

Categories: , Tags: , ,


Hosted by Webfaction

Counter...