fix issue106: allow parametrize to be applied per-class/per-module
This commit is contained in:
parent
ccc1b21ebd
commit
f2c8a837af
|
@ -7,6 +7,8 @@ Changes between 2.2.1 and 2.2.2.dev
|
||||||
produce better output
|
produce better output
|
||||||
- fix issue102: report more useful errors and hints for when a
|
- fix issue102: report more useful errors and hints for when a
|
||||||
test directory was renamed and some pyc/__pycache__ remain
|
test directory was renamed and some pyc/__pycache__ remain
|
||||||
|
- fix issue106: allow parametrize to be applied multiple times
|
||||||
|
e.g. from module, class and at function level.
|
||||||
|
|
||||||
Changes between 2.2.0 and 2.2.1
|
Changes between 2.2.0 and 2.2.1
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
|
@ -224,22 +224,3 @@ class MarkInfo:
|
||||||
for args, kwargs in self._arglist:
|
for args, kwargs in self._arglist:
|
||||||
yield MarkInfo(self.name, args, kwargs)
|
yield MarkInfo(self.name, args, kwargs)
|
||||||
|
|
||||||
def pytest_itemcollected(item):
|
|
||||||
if not isinstance(item, pytest.Function):
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
func = item.obj.__func__
|
|
||||||
except AttributeError:
|
|
||||||
func = getattr(item.obj, 'im_func', item.obj)
|
|
||||||
pyclasses = (pytest.Class, pytest.Module)
|
|
||||||
for node in item.listchain():
|
|
||||||
if isinstance(node, pyclasses):
|
|
||||||
marker = getattr(node.obj, 'pytestmark', None)
|
|
||||||
if marker is not None:
|
|
||||||
if isinstance(marker, list):
|
|
||||||
for mark in marker:
|
|
||||||
mark(func)
|
|
||||||
else:
|
|
||||||
marker(func)
|
|
||||||
node = node.parent
|
|
||||||
item.keywords.update(py.builtin._getfuncdict(func))
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ def pytest_generate_tests(metafunc):
|
||||||
param = metafunc.function.parametrize
|
param = metafunc.function.parametrize
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return
|
return
|
||||||
metafunc.parametrize(*param.args, **param.kwargs)
|
for p in param:
|
||||||
|
metafunc.parametrize(*p.args, **p.kwargs)
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
config.addinivalue_line("markers",
|
config.addinivalue_line("markers",
|
||||||
|
@ -222,6 +223,7 @@ class PyCollectorMixin(PyobjMixin, pytest.Collector):
|
||||||
cls = clscol and clscol.obj or None
|
cls = clscol and clscol.obj or None
|
||||||
metafunc = Metafunc(funcobj, config=self.config,
|
metafunc = Metafunc(funcobj, config=self.config,
|
||||||
cls=cls, module=module)
|
cls=cls, module=module)
|
||||||
|
transfer_markers(metafunc)
|
||||||
gentesthook = self.config.hook.pytest_generate_tests
|
gentesthook = self.config.hook.pytest_generate_tests
|
||||||
extra = [module]
|
extra = [module]
|
||||||
if cls is not None:
|
if cls is not None:
|
||||||
|
@ -239,6 +241,20 @@ class PyCollectorMixin(PyobjMixin, pytest.Collector):
|
||||||
l.append(function)
|
l.append(function)
|
||||||
return l
|
return l
|
||||||
|
|
||||||
|
def transfer_markers(metafunc):
|
||||||
|
# XXX this should rather be code in the mark plugin or the mark
|
||||||
|
# plugin should merge with the python plugin.
|
||||||
|
for holder in (metafunc.cls, metafunc.module):
|
||||||
|
try:
|
||||||
|
pytestmark = holder.pytestmark
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
if isinstance(pytestmark, list):
|
||||||
|
for mark in pytestmark:
|
||||||
|
mark(metafunc.function)
|
||||||
|
else:
|
||||||
|
pytestmark(metafunc.function)
|
||||||
|
|
||||||
|
|
||||||
class Module(pytest.File, PyCollectorMixin):
|
class Module(pytest.File, PyCollectorMixin):
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
|
@ -559,7 +575,7 @@ class CallSpec2(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
return "-".join(filter(None, self._idlist))
|
return "-".join(map(str, filter(None, self._idlist)))
|
||||||
|
|
||||||
def setmulti(self, valtype, argnames, valset, id):
|
def setmulti(self, valtype, argnames, valset, id):
|
||||||
for arg,val in zip(argnames, valset):
|
for arg,val in zip(argnames, valset):
|
||||||
|
|
|
@ -228,26 +228,26 @@ class TestFunctional:
|
||||||
keywords = item.keywords
|
keywords = item.keywords
|
||||||
marker = keywords['hello']
|
marker = keywords['hello']
|
||||||
assert marker.args == ("pos0", "pos1")
|
assert marker.args == ("pos0", "pos1")
|
||||||
assert marker.kwargs == {'x': 3, 'y': 2, 'z': 4}
|
assert marker.kwargs == {'x': 1, 'y': 2, 'z': 4}
|
||||||
|
|
||||||
# test the new __iter__ interface
|
# test the new __iter__ interface
|
||||||
l = list(marker)
|
l = list(marker)
|
||||||
assert len(l) == 3
|
assert len(l) == 3
|
||||||
assert l[0].args == ("pos0",)
|
assert l[0].args == ("pos0",)
|
||||||
pytest.xfail(reason="needs reordering of parametrize transfermarks")
|
|
||||||
assert l[1].args == ()
|
assert l[1].args == ()
|
||||||
assert l[2].args == ("pos1", )
|
assert l[2].args == ("pos1", )
|
||||||
|
|
||||||
def test_mark_other(self, testdir):
|
def test_mark_with_wrong_marker(self, testdir):
|
||||||
pytest.raises(TypeError, '''
|
reprec = testdir.inline_runsource("""
|
||||||
testdir.getitem("""
|
|
||||||
import pytest
|
import pytest
|
||||||
class pytestmark:
|
class pytestmark:
|
||||||
pass
|
pass
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
''')
|
l = reprec.getfailedcollections()
|
||||||
|
assert len(l) == 1
|
||||||
|
assert "TypeError" in str(l[0].longrepr)
|
||||||
|
|
||||||
def test_mark_dynamically_in_funcarg(self, testdir):
|
def test_mark_dynamically_in_funcarg(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
|
|
@ -1048,6 +1048,23 @@ class TestMetafunc:
|
||||||
assert metafunc._calls[1].funcargs == dict(x=3, y=4)
|
assert metafunc._calls[1].funcargs == dict(x=3, y=4)
|
||||||
assert metafunc._calls[1].id == "3-4"
|
assert metafunc._calls[1].id == "3-4"
|
||||||
|
|
||||||
|
def test_parametrize_multiple_times(self, testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
pytestmark = pytest.mark.parametrize("x", [1,2])
|
||||||
|
def test_func(x):
|
||||||
|
assert 0, x
|
||||||
|
class TestClass:
|
||||||
|
pytestmark = pytest.mark.parametrize("y", [3,4])
|
||||||
|
def test_meth(self, x, y):
|
||||||
|
assert 0, x
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
assert result.ret == 1
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*6 fail*",
|
||||||
|
])
|
||||||
|
|
||||||
class TestMetafuncFunctional:
|
class TestMetafuncFunctional:
|
||||||
def test_attributes(self, testdir):
|
def test_attributes(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
|
|
Loading…
Reference in New Issue