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
|
||||
- fix issue102: report more useful errors and hints for when a
|
||||
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
|
||||
----------------------------------------
|
||||
|
|
|
@ -224,22 +224,3 @@ class MarkInfo:
|
|||
for args, kwargs in self._arglist:
|
||||
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
|
||||
except AttributeError:
|
||||
return
|
||||
metafunc.parametrize(*param.args, **param.kwargs)
|
||||
for p in param:
|
||||
metafunc.parametrize(*p.args, **p.kwargs)
|
||||
|
||||
def pytest_configure(config):
|
||||
config.addinivalue_line("markers",
|
||||
|
@ -222,6 +223,7 @@ class PyCollectorMixin(PyobjMixin, pytest.Collector):
|
|||
cls = clscol and clscol.obj or None
|
||||
metafunc = Metafunc(funcobj, config=self.config,
|
||||
cls=cls, module=module)
|
||||
transfer_markers(metafunc)
|
||||
gentesthook = self.config.hook.pytest_generate_tests
|
||||
extra = [module]
|
||||
if cls is not None:
|
||||
|
@ -239,6 +241,20 @@ class PyCollectorMixin(PyobjMixin, pytest.Collector):
|
|||
l.append(function)
|
||||
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):
|
||||
def _getobj(self):
|
||||
|
@ -559,7 +575,7 @@ class CallSpec2(object):
|
|||
|
||||
@property
|
||||
def id(self):
|
||||
return "-".join(filter(None, self._idlist))
|
||||
return "-".join(map(str, filter(None, self._idlist)))
|
||||
|
||||
def setmulti(self, valtype, argnames, valset, id):
|
||||
for arg,val in zip(argnames, valset):
|
||||
|
|
|
@ -228,26 +228,26 @@ class TestFunctional:
|
|||
keywords = item.keywords
|
||||
marker = keywords['hello']
|
||||
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
|
||||
l = list(marker)
|
||||
assert len(l) == 3
|
||||
assert l[0].args == ("pos0",)
|
||||
pytest.xfail(reason="needs reordering of parametrize transfermarks")
|
||||
assert l[1].args == ()
|
||||
assert l[2].args == ("pos1", )
|
||||
|
||||
def test_mark_other(self, testdir):
|
||||
pytest.raises(TypeError, '''
|
||||
testdir.getitem("""
|
||||
def test_mark_with_wrong_marker(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
import pytest
|
||||
class pytestmark:
|
||||
pass
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
''')
|
||||
l = reprec.getfailedcollections()
|
||||
assert len(l) == 1
|
||||
assert "TypeError" in str(l[0].longrepr)
|
||||
|
||||
def test_mark_dynamically_in_funcarg(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
|
|
|
@ -1048,6 +1048,23 @@ class TestMetafunc:
|
|||
assert metafunc._calls[1].funcargs == dict(x=3, y=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:
|
||||
def test_attributes(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
|
|
Loading…
Reference in New Issue