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
This commit is contained in:
parent
f203401964
commit
dba2a8bc64
|
@ -24,6 +24,9 @@ Changes between 2.3.2 and 2.3.3.dev
|
||||||
- in tracebacks *,** arg values are now shown next to normal arguments
|
- in tracebacks *,** arg values are now shown next to normal arguments
|
||||||
(thanks Manuel Jacob)
|
(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
|
Changes between 2.3.1 and 2.3.2
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#
|
#
|
||||||
__version__ = '2.3.3.dev3'
|
__version__ = '2.3.3.dev4'
|
||||||
|
|
|
@ -1659,8 +1659,14 @@ class FixtureDef:
|
||||||
def getfuncargnames(function, startindex=None):
|
def getfuncargnames(function, startindex=None):
|
||||||
# XXX merge with main.py's varnames
|
# XXX merge with main.py's varnames
|
||||||
#assert not inspect.isclass(function)
|
#assert not inspect.isclass(function)
|
||||||
|
realfunction = function
|
||||||
|
while hasattr(realfunction, "__wrapped__"):
|
||||||
|
realfunction = realfunction.__wrapped__
|
||||||
if startindex is None:
|
if startindex is None:
|
||||||
startindex = inspect.ismethod(function) and 1 or 0
|
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]
|
argnames = inspect.getargs(py.code.getrawcode(function))[0]
|
||||||
defaults = getattr(function, 'func_defaults',
|
defaults = getattr(function, 'func_defaults',
|
||||||
getattr(function, '__defaults__', None)) or ()
|
getattr(function, '__defaults__', None)) or ()
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -24,7 +24,7 @@ def main():
|
||||||
name='pytest',
|
name='pytest',
|
||||||
description='py.test: simple powerful testing with Python',
|
description='py.test: simple powerful testing with Python',
|
||||||
long_description = long_description,
|
long_description = long_description,
|
||||||
version='2.3.3.dev3',
|
version='2.3.3.dev4',
|
||||||
url='http://pytest.org',
|
url='http://pytest.org',
|
||||||
license='MIT license',
|
license='MIT license',
|
||||||
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||||
|
|
|
@ -541,59 +541,6 @@ class TestRequestCachedSetup:
|
||||||
"*ZeroDivisionError*",
|
"*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:
|
class TestFixtureUsages:
|
||||||
def test_noargfixturedec(self, testdir):
|
def test_noargfixturedec(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
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)
|
|
@ -253,7 +253,7 @@ class TestFunctional:
|
||||||
""")
|
""")
|
||||||
items, rec = testdir.inline_genitems(p)
|
items, rec = testdir.inline_genitems(p)
|
||||||
for item in items:
|
for item in items:
|
||||||
print item, item.keywords
|
print (item, item.keywords)
|
||||||
assert 'a' in item.keywords
|
assert 'a' in item.keywords
|
||||||
|
|
||||||
def test_mark_with_wrong_marker(self, testdir):
|
def test_mark_with_wrong_marker(self, testdir):
|
||||||
|
|
|
@ -103,21 +103,13 @@ def test_nose_setup_func_failure_2(testdir):
|
||||||
my_teardown = 2
|
my_teardown = 2
|
||||||
|
|
||||||
def test_hello():
|
def test_hello():
|
||||||
print (l)
|
assert l == []
|
||||||
assert l == [1]
|
|
||||||
|
|
||||||
def test_world():
|
|
||||||
print (l)
|
|
||||||
assert l == [1,2]
|
|
||||||
|
|
||||||
test_hello.setup = my_setup
|
test_hello.setup = my_setup
|
||||||
test_hello.teardown = my_teardown
|
test_hello.teardown = my_teardown
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, '-p', 'nose')
|
reprec = testdir.inline_run()
|
||||||
result.stdout.fnmatch_lines([
|
reprec.assertoutcome(passed=1)
|
||||||
"*TypeError: 'int' object is not callable*"
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
def test_nose_setup_partial(testdir):
|
def test_nose_setup_partial(testdir):
|
||||||
py.test.importorskip("functools")
|
py.test.importorskip("functools")
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -21,6 +21,8 @@ commands= py.test --genscript=pytest1
|
||||||
changedir=.
|
changedir=.
|
||||||
basepython=python2.7
|
basepython=python2.7
|
||||||
deps=pytest-xdist
|
deps=pytest-xdist
|
||||||
|
:pypi:mock
|
||||||
|
:pypi:nose
|
||||||
commands=
|
commands=
|
||||||
py.test -n3 -rfsxX \
|
py.test -n3 -rfsxX \
|
||||||
--junitxml={envlogdir}/junit-{envname}.xml testing
|
--junitxml={envlogdir}/junit-{envname}.xml testing
|
||||||
|
|
Loading…
Reference in New Issue