From 6976d40b5896696719d229e02a5a847460704e7e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 16 Sep 2014 22:53:08 -0300 Subject: [PATCH 1/2] Deprecating mock in favor of mocker --- README.rst | 37 ++++++++++++++++++++------------ pytest_mock.py | 16 ++++++++++++-- test_pytest_mock.py | 52 ++++++++++++++++++++++++++++++++------------- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/README.rst b/README.rst index 69947e7..212869f 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ pytest-mock =========== -This plugin installs a ``mock`` fixture which is a thin-wrapper around the patching API +This plugin installs a ``mocker`` fixture which is a thin-wrapper around the patching API provided by the excellent `mock `_ package, but with the benefit of not having to worry about undoing patches at the end of a test: @@ -10,8 +10,8 @@ of a test: .. code-block:: python - def test_unix_fs(mock): - mock.patch('os.remove') + def test_unix_fs(mocker): + mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') @@ -40,27 +40,38 @@ of a test: Usage ===== -The ``mock`` fixture has the same API as +The ``mocker`` fixture has the same API as `mock.patch `_, supporting the same arguments: .. code-block:: python - def test_foo(mock): + def test_foo(mocker): # all valid calls - mock.patch('os.remove') - mock.patch.object(os, 'listdir', autospec=True) - mocked = mock.patch('os.path.isfile') + mocker.patch('os.remove') + mocker.patch.object(os, 'listdir', autospec=True) + mocked_isfile = mocker.patch('os.path.isfile') The supported methods are: -* ``mock.patch``: see http://www.voidspace.org.uk/python/mock/patch.html#patch. -* ``mock.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object. -* ``mock.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple. -* ``mock.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict. -* ``mock.stopall()``: stops all active patches at this point. +* ``mocker.patch``: see http://www.voidspace.org.uk/python/mock/patch.html#patch. +* ``mocker.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object. +* ``mocker.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple. +* ``mocker.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict. +* ``mocker.stopall()``: stops all active patches at this point. +Note +---- + +Prior to version ``0.4.0``, the ``mocker`` fixture was named ``mock``. +This was changed because naming the fixture ``mock`` conflicts with the +actual ``mock`` module, which made using it awkward when access to both the +module and the plugin were required within a test. + +The old fixture ``mock`` still works, but its use is discouraged and will be +removed in version ``1.0``. + Requirements ============ diff --git a/pytest_mock.py b/pytest_mock.py index f90d07b..492a5ff 100644 --- a/pytest_mock.py +++ b/pytest_mock.py @@ -68,11 +68,23 @@ def __call__(self, *args, **kwargs): @pytest.yield_fixture -def mock(): +def mocker(): """ return an object that has the same interface to the `mock` module, but takes care of automatically undoing all patches after each test method. """ result = MockFixture() yield result - result.stopall() \ No newline at end of file + result.stopall() + + +@pytest.yield_fixture +def mock(): + """ + Same as "mocker", but kept only for backward compatibility. + """ + import warnings + warnings.warn('"mock" fixture has been deprecated, use "mocker" instead', + DeprecationWarning) + for m in mocker(): + yield m \ No newline at end of file diff --git a/test_pytest_mock.py b/test_pytest_mock.py index 32fb57a..112c922 100644 --- a/test_pytest_mock.py +++ b/test_pytest_mock.py @@ -3,6 +3,8 @@ import pytest +pytest_plugins = 'pytester' + class UnixFS(object): """ Wrapper to os functions to simulate a Unix file system, used for testing @@ -19,7 +21,7 @@ def ls(cls, path): @pytest.fixture -def check_unix_fs_mocked(tmpdir, mock): +def check_unix_fs_mocked(tmpdir, mocker): """ performs a standard test in a UnixFS, assuming that both `os.remove` and `os.listdir` have been mocked previously. @@ -40,7 +42,7 @@ def check(mocked_rm, mocked_ls): assert UnixFS.ls(str(tmpdir)) == ['bar.txt'] mocked_ls.assert_called_once_with(str(tmpdir)) - mock.stopall() + mocker.stopall() assert UnixFS.ls(str(tmpdir)) == ['foo.txt'] UnixFS.rm(str(file_name)) @@ -49,43 +51,63 @@ def check(mocked_rm, mocked_ls): return check -def mock_using_patch_object(mock): - return mock.patch.object(os, 'remove'), mock.patch.object(os, 'listdir') +def mock_using_patch_object(mocker): + return mocker.patch.object(os, 'remove'), mocker.patch.object(os, 'listdir') -def mock_using_patch(mock): - return mock.patch('os.remove'), mock.patch('os.listdir') +def mock_using_patch(mocker): + return mocker.patch('os.remove'), mocker.patch('os.listdir') -def mock_using_patch_multiple(mock): +def mock_using_patch_multiple(mocker): from pytest_mock import mock_module - r = mock.patch.multiple('os', remove=mock_module.DEFAULT, - listdir=mock_module.DEFAULT) + r = mocker.patch.multiple('os', remove=mock_module.DEFAULT, + listdir=mock_module.DEFAULT) return r['remove'], r['listdir'] @pytest.mark.parametrize('mock_fs', [mock_using_patch_object, mock_using_patch, mock_using_patch_multiple], ) -def test_mock_patches(mock_fs, mock, check_unix_fs_mocked): +def test_mock_patches(mock_fs, mocker, check_unix_fs_mocked): """ Installs mocks into `os` functions and performs a standard testing of mock functionality. We parametrize different mock methods to ensure all (intended, at least) mock API is covered. """ - mock_fs(mock) - mocked_rm, mocked_ls = mock_fs(mock) + # mock it twice on purpose to ensure we unmock it correctly later + mock_fs(mocker) + mocked_rm, mocked_ls = mock_fs(mocker) check_unix_fs_mocked(mocked_rm, mocked_ls) -def test_mock_patch_dict(mock): +def test_mock_patch_dict(mocker): """ Testing :param mock: """ x = {'original': 1} - mock.patch.dict(x, values=[('new', 10)], clear=True) + mocker.patch.dict(x, values=[('new', 10)], clear=True) assert x == {'new': 10} - mock.stopall() + mocker.stopall() assert x == {'original': 1} + + +def test_mock_fixture_is_deprecated(testdir): + """ + Test that a warning emitted when using deprecated "mock" fixture. + """ + testdir.makepyfile(''' + import warnings + import os + warnings.simplefilter('always') + + def test_foo(mock, tmpdir): + mock.patch('os.listdir', return_value=['mocked']) + assert os.listdir(str(tmpdir)) == ['mocked'] + mock.stopall() + assert os.listdir(str(tmpdir)) == [] + ''') + result = testdir.runpytest('-s') + result.stderr.fnmatch_lines(['*"mock" fixture has been deprecated*']) From 68f3da830b01455d62a54673c4e5f5cd8ae2c9e9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 16 Sep 2014 22:53:23 -0300 Subject: [PATCH 2/2] Bumping version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cf9b0d8..2317851 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='pytest-mock', - version='0.3.0', + version='0.4.0', entry_points={ 'pytest11': ['pytest-mock = pytest_mock'], },