Merge branch 'master' of github.com:wolever/parameterized
diff --git a/parameterized/parameterized.py b/parameterized/parameterized.py index 5b0a336..775a1cd 100644 --- a/parameterized/parameterized.py +++ b/parameterized/parameterized.py
@@ -49,6 +49,27 @@ def skip_on_empty_helper(*a, **kw): raise SkipTest("parameterized input is empty") +def reapply_patches_if_need(func): + + def dummy_wrapper(orgfunc): + @wraps(orgfunc) + def dummy_func(*args, **kwargs): + return orgfunc(*args, **kwargs) + return dummy_func + + if hasattr(func, 'patchings'): + func = dummy_wrapper(func) + tmp_patchings = func.patchings + delattr(func, 'patchings') + for patch_obj in tmp_patchings: + func = patch_obj.decorate_callable(func) + return func + +def delete_patches_if_need(func): + if hasattr(func, 'patchings'): + func.patchings[:] = [] + + class param(_param): """ Represents a single parameter to a test case. @@ -459,8 +480,16 @@ for num, p in enumerate(paramters): name = name_func(f, num, p) - frame_locals[name] = cls.param_as_standalone_func(p, f, name) + # If the original function has patches applied by 'mock.patch', + # re-construct all patches on the just former decoration layer + # of param_as_standalone_func so as not to share + # patch objects between new functions + nf = reapply_patches_if_need(f) + frame_locals[name] = cls.param_as_standalone_func(p, nf, name) frame_locals[name].__doc__ = doc_func(f, num, p) + # Delete original patches to prevent new function from evaluating + # original patching object as well as re-constructed patches. + delete_patches_if_need(f) f.__test__ = False return parameterized_expand_wrapper
diff --git a/parameterized/test.py b/parameterized/test.py index 2a1f26b..f470127 100644 --- a/parameterized/test.py +++ b/parameterized/test.py
@@ -1,6 +1,7 @@ # coding=utf-8 import inspect +import mock from unittest import TestCase from nose.tools import assert_equal, assert_raises @@ -100,6 +101,74 @@ return custom_naming_func +@mock.patch("os.getpid") +class TestParameterizedExpandWithMockPatchForClass(TestCase): + expect([ + "test_one_function_patch_decorator('foo1', 'umask', 'getpid')", + "test_one_function_patch_decorator('foo0', 'umask', 'getpid')", + "test_one_function_patch_decorator(42, 'umask', 'getpid')", + ]) + + @parameterized.expand([(42, ), "foo0", param("foo1")]) + @mock.patch("os.umask") + def test_one_function_patch_decorator(self, foo, mock_umask, mock_getpid): + missing_tests.remove("test_one_function_patch_decorator(%r, %r, %r)" % + (foo, mock_umask._mock_name, + mock_getpid._mock_name)) + + expect([ + "test_multiple_function_patch_decorator" + "(42, 51, 'umask', 'fdopen', 'getpid')", + "test_multiple_function_patch_decorator" + "('foo0', 'bar0', 'umask', 'fdopen', 'getpid')", + "test_multiple_function_patch_decorator" + "('foo1', 'bar1', 'umask', 'fdopen', 'getpid')", + ]) + + @parameterized.expand([(42, 51), ("foo0", "bar0"), param("foo1", "bar1")]) + @mock.patch("os.fdopen") + @mock.patch("os.umask") + def test_multiple_function_patch_decorator(self, foo, bar, mock_umask, + mock_fdopen, mock_getpid): + missing_tests.remove("test_multiple_function_patch_decorator" + "(%r, %r, %r, %r, %r)" % + (foo, bar, mock_umask._mock_name, + mock_fdopen._mock_name, mock_getpid._mock_name)) + + +class TestParameterizedExpandWithNoMockPatchForClass(TestCase): + expect([ + "test_one_function_patch_decorator('foo1', 'umask')", + "test_one_function_patch_decorator('foo0', 'umask')", + "test_one_function_patch_decorator(42, 'umask')", + ]) + + @parameterized.expand([(42, ), "foo0", param("foo1")]) + @mock.patch("os.umask") + def test_one_function_patch_decorator(self, foo, mock_umask): + missing_tests.remove("test_one_function_patch_decorator(%r, %r)" % + (foo, mock_umask._mock_name)) + + expect([ + "test_multiple_function_patch_decorator" + "(42, 51, 'umask', 'fdopen')", + "test_multiple_function_patch_decorator" + "('foo0', 'bar0', 'umask', 'fdopen')", + "test_multiple_function_patch_decorator" + "('foo1', 'bar1', 'umask', 'fdopen')", + ]) + + @parameterized.expand([(42, 51), ("foo0", "bar0"), param("foo1", "bar1")]) + @mock.patch("os.fdopen") + @mock.patch("os.umask") + def test_multiple_function_patch_decorator(self, foo, bar, mock_umask, + mock_fdopen): + missing_tests.remove("test_multiple_function_patch_decorator" + "(%r, %r, %r, %r)" % + (foo, bar, mock_umask._mock_name, + mock_fdopen._mock_name)) + + class TestParamerizedOnTestCase(TestCase): expect([ "test_on_TestCase('foo0', bar=None)",
diff --git a/tox.ini b/tox.ini index c75a0ab..c58219f 100644 --- a/tox.ini +++ b/tox.ini
@@ -4,6 +4,7 @@ [testenv] deps= nose + mock nose2: nose2 pytest: pytest>=2 unit2: unittest2