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