Commits

holger krekel committed 8bd54f9

fix issue217 - to support @mock.patch with pytest funcarg-fixtures, also split out python integration tests into python/integration.py and fix nose/mark tests

Comments (0)

Files changed (9)

 - in tracebacks *,** arg values are now shown next to normal arguments
   (thanks Manuel Jacob)
 
+- fix issue217 - support mock.patch with pytest's fixtures - note that
+  you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
+
 Changes between 2.3.1 and 2.3.2
 -----------------------------------
 

_pytest/__init__.py

 #
-__version__ = '2.3.3.dev3'
+__version__ = '2.3.3.dev4'

_pytest/python.py

 def getfuncargnames(function, startindex=None):
     # XXX merge with main.py's varnames
     #assert not inspect.isclass(function)
+    realfunction = function
+    while hasattr(realfunction, "__wrapped__"):
+        realfunction = realfunction.__wrapped__
     if startindex is None:
         startindex = inspect.ismethod(function) and 1 or 0
+    if realfunction != function:
+        startindex += len(getattr(function, "patchings", []))
+        function = realfunction
     argnames = inspect.getargs(py.code.getrawcode(function))[0]
     defaults = getattr(function, 'func_defaults',
                        getattr(function, '__defaults__', None)) or ()
         name='pytest',
         description='py.test: simple powerful testing with Python',
         long_description = long_description,
-        version='2.3.3.dev3',
+        version='2.3.3.dev4',
         url='http://pytest.org',
         license='MIT license',
         platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

testing/python/fixture.py

             "*ZeroDivisionError*",
         ])
 
-class TestOEJSKITSpecials:
-    def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
-        testdir.makeconftest("""
-            import pytest
-            def pytest_pycollect_makeitem(collector, name, obj):
-                if name == "MyClass":
-                    return MyCollector(name, parent=collector)
-            class MyCollector(pytest.Collector):
-                def reportinfo(self):
-                    return self.fspath, 3, "xyz"
-        """)
-        modcol = testdir.getmodulecol("""
-            def pytest_funcarg__arg1(request):
-                return 42
-            class MyClass:
-                pass
-        """)
-        # this hook finds funcarg factories
-        rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
-        clscol = rep.result[0]
-        clscol.obj = lambda arg1: None
-        clscol.funcargs = {}
-        funcargs.fillfixtures(clscol)
-        assert clscol.funcargs['arg1'] == 42
-
-    def test_autouse_fixture(self, testdir): # rough jstests usage
-        testdir.makeconftest("""
-            import pytest
-            def pytest_pycollect_makeitem(collector, name, obj):
-                if name == "MyClass":
-                    return MyCollector(name, parent=collector)
-            class MyCollector(pytest.Collector):
-                def reportinfo(self):
-                    return self.fspath, 3, "xyz"
-        """)
-        modcol = testdir.getmodulecol("""
-            import pytest
-            @pytest.fixture(autouse=True)
-            def hello():
-                pass
-            def pytest_funcarg__arg1(request):
-                return 42
-            class MyClass:
-                pass
-        """)
-        # this hook finds funcarg factories
-        rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
-        clscol = rep.result[0]
-        clscol.obj = lambda: None
-        clscol.funcargs = {}
-        funcargs.fillfixtures(clscol)
-        assert not clscol.funcargs
-
 class TestFixtureUsages:
     def test_noargfixturedec(self, testdir):
         testdir.makepyfile("""

testing/python/integration.py

+import pytest, py, sys
+
+class TestOEJSKITSpecials:
+    def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
+        testdir.makeconftest("""
+            import pytest
+            def pytest_pycollect_makeitem(collector, name, obj):
+                if name == "MyClass":
+                    return MyCollector(name, parent=collector)
+            class MyCollector(pytest.Collector):
+                def reportinfo(self):
+                    return self.fspath, 3, "xyz"
+        """)
+        modcol = testdir.getmodulecol("""
+            def pytest_funcarg__arg1(request):
+                return 42
+            class MyClass:
+                pass
+        """)
+        # this hook finds funcarg factories
+        rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
+        clscol = rep.result[0]
+        clscol.obj = lambda arg1: None
+        clscol.funcargs = {}
+        pytest._fillfuncargs(clscol)
+        assert clscol.funcargs['arg1'] == 42
+
+    def test_autouse_fixture(self, testdir): # rough jstests usage
+        testdir.makeconftest("""
+            import pytest
+            def pytest_pycollect_makeitem(collector, name, obj):
+                if name == "MyClass":
+                    return MyCollector(name, parent=collector)
+            class MyCollector(pytest.Collector):
+                def reportinfo(self):
+                    return self.fspath, 3, "xyz"
+        """)
+        modcol = testdir.getmodulecol("""
+            import pytest
+            @pytest.fixture(autouse=True)
+            def hello():
+                pass
+            def pytest_funcarg__arg1(request):
+                return 42
+            class MyClass:
+                pass
+        """)
+        # this hook finds funcarg factories
+        rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
+        clscol = rep.result[0]
+        clscol.obj = lambda: None
+        clscol.funcargs = {}
+        pytest._fillfuncargs(clscol)
+        assert not clscol.funcargs
+
+
+class TestMockDecoration:
+    def test_wrapped_getfuncargnames(self):
+        from _pytest.python import getfuncargnames
+        def wrap(f):
+            def func():
+                pass
+            func.__wrapped__ = f
+            return func
+        @wrap
+        def f(x):
+            pass
+        l = getfuncargnames(f)
+        assert l == ("x",)
+
+    def test_wrapped_getfuncargnames_patching(self):
+        from _pytest.python import getfuncargnames
+        def wrap(f):
+            def func():
+                pass
+            func.__wrapped__ = f
+            func.patchings = ["qwe"]
+            return func
+        @wrap
+        def f(x, y, z):
+            pass
+        l = getfuncargnames(f)
+        assert l == ("y", "z")
+
+    def test_unittest_mock(self, testdir):
+        pytest.importorskip("unittest.mock")
+        testdir.makepyfile("""
+            import unittest.mock
+            class T(unittest.TestCase):
+                @unittest.mock.patch("os.path.abspath")
+                def test_hello(self, abspath):
+                    import os
+                    os.path.abspath("hello")
+                    abspath.assert_any_call("hello")
+        """)
+        reprec = testdir.inline_run()
+        reprec.assertoutcome(passed=1)
+
+    def test_mock(self, testdir):
+        pytest.importorskip("mock", "1.0.1")
+        testdir.makepyfile("""
+            import os
+            import unittest
+            import mock
+
+            class T(unittest.TestCase):
+                @mock.patch("os.path.abspath")
+                def test_hello(self, abspath):
+                    os.path.abspath("hello")
+                    abspath.assert_any_call("hello")
+            @mock.patch("os.path.abspath")
+            @mock.patch("os.path.normpath")
+            def test_someting(normpath, abspath, tmpdir):
+                abspath.return_value = "this"
+                os.path.normpath(os.path.abspath("hello"))
+                normpath.assert_any_call("this")
+        """)
+        reprec = testdir.inline_run()
+        reprec.assertoutcome(passed=2)

testing/test_mark.py

         """)
         items, rec = testdir.inline_genitems(p)
         for item in items:
-            print item, item.keywords
+            print (item, item.keywords)
             assert 'a' in item.keywords
 
     def test_mark_with_wrong_marker(self, testdir):

testing/test_nose.py

         my_teardown = 2
 
         def test_hello():
-            print (l)
-            assert l == [1]
-
-        def test_world():
-            print (l)
-            assert l == [1,2]
+            assert l == []
 
         test_hello.setup = my_setup
         test_hello.teardown = my_teardown
     """)
-    result = testdir.runpytest(p, '-p', 'nose')
-    result.stdout.fnmatch_lines([
-        "*TypeError: 'int' object is not callable*"
-    ])
-
+    reprec = testdir.inline_run()
+    reprec.assertoutcome(passed=1)
 
 def test_nose_setup_partial(testdir):
     py.test.importorskip("functools")
 changedir=.
 basepython=python2.7
 deps=pytest-xdist
+    :pypi:mock
+    :pypi:nose
 commands=
   py.test -n3 -rfsxX \
         --junitxml={envlogdir}/junit-{envname}.xml testing