Merge pull request #1535 from palaviv/parametrize-test-ids-hook
introduce pytest_make_parametrize_id hook
This commit is contained in:
commit
6cc56b4a1b
|
@ -27,7 +27,8 @@
|
||||||
whether to filter the traceback based on the ``ExceptionInfo`` object passed
|
whether to filter the traceback based on the ``ExceptionInfo`` object passed
|
||||||
to it.
|
to it.
|
||||||
|
|
||||||
*
|
* New ``pytest_make_parametrize_id`` hook.
|
||||||
|
Thanks `@palaviv`_ for the PR.
|
||||||
|
|
||||||
**Changes**
|
**Changes**
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,12 @@ def pytest_pyfunc_call(pyfuncitem):
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
""" generate (multiple) parametrized calls to a test function."""
|
""" generate (multiple) parametrized calls to a test function."""
|
||||||
|
|
||||||
|
@hookspec(firstresult=True)
|
||||||
|
def pytest_make_parametrize_id(config, val):
|
||||||
|
"""Return a user-friendly string representation of the given ``val`` that will be used
|
||||||
|
by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``.
|
||||||
|
"""
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# generic runtest related hooks
|
# generic runtest related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
|
@ -342,6 +342,9 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
res = list(collector._genfunctions(name, obj))
|
res = list(collector._genfunctions(name, obj))
|
||||||
outcome.force_result(res)
|
outcome.force_result(res)
|
||||||
|
|
||||||
|
def pytest_make_parametrize_id(config, val):
|
||||||
|
return None
|
||||||
|
|
||||||
def is_generator(func):
|
def is_generator(func):
|
||||||
try:
|
try:
|
||||||
return _pytest._code.getrawcode(func).co_flags & 32 # generator function
|
return _pytest._code.getrawcode(func).co_flags & 32 # generator function
|
||||||
|
@ -1038,7 +1041,7 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||||
if ids and len(ids) != len(argvalues):
|
if ids and len(ids) != len(argvalues):
|
||||||
raise ValueError('%d tests specified with %d ids' %(
|
raise ValueError('%d tests specified with %d ids' %(
|
||||||
len(argvalues), len(ids)))
|
len(argvalues), len(ids)))
|
||||||
ids = idmaker(argnames, argvalues, idfn, ids)
|
ids = idmaker(argnames, argvalues, idfn, ids, self.config)
|
||||||
newcalls = []
|
newcalls = []
|
||||||
for callspec in self._calls or [CallSpec2(self)]:
|
for callspec in self._calls or [CallSpec2(self)]:
|
||||||
for param_index, valset in enumerate(argvalues):
|
for param_index, valset in enumerate(argvalues):
|
||||||
|
@ -1138,7 +1141,7 @@ else:
|
||||||
return val.encode('unicode-escape')
|
return val.encode('unicode-escape')
|
||||||
|
|
||||||
|
|
||||||
def _idval(val, argname, idx, idfn):
|
def _idval(val, argname, idx, idfn, config=None):
|
||||||
if idfn:
|
if idfn:
|
||||||
try:
|
try:
|
||||||
s = idfn(val)
|
s = idfn(val)
|
||||||
|
@ -1147,6 +1150,11 @@ def _idval(val, argname, idx, idfn):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if config:
|
||||||
|
hook_id = config.hook.pytest_make_parametrize_id(config=config, val=val)
|
||||||
|
if hook_id:
|
||||||
|
return hook_id
|
||||||
|
|
||||||
if isinstance(val, (bytes, str)) or (_PY2 and isinstance(val, unicode)):
|
if isinstance(val, (bytes, str)) or (_PY2 and isinstance(val, unicode)):
|
||||||
return _escape_strings(val)
|
return _escape_strings(val)
|
||||||
elif isinstance(val, (float, int, bool, NoneType)):
|
elif isinstance(val, (float, int, bool, NoneType)):
|
||||||
|
@ -1159,16 +1167,16 @@ def _idval(val, argname, idx, idfn):
|
||||||
return val.__name__
|
return val.__name__
|
||||||
return str(argname)+str(idx)
|
return str(argname)+str(idx)
|
||||||
|
|
||||||
def _idvalset(idx, valset, argnames, idfn, ids):
|
def _idvalset(idx, valset, argnames, idfn, ids, config=None):
|
||||||
if ids is None or ids[idx] is None:
|
if ids is None or ids[idx] is None:
|
||||||
this_id = [_idval(val, argname, idx, idfn)
|
this_id = [_idval(val, argname, idx, idfn, config)
|
||||||
for val, argname in zip(valset, argnames)]
|
for val, argname in zip(valset, argnames)]
|
||||||
return "-".join(this_id)
|
return "-".join(this_id)
|
||||||
else:
|
else:
|
||||||
return _escape_strings(ids[idx])
|
return _escape_strings(ids[idx])
|
||||||
|
|
||||||
def idmaker(argnames, argvalues, idfn=None, ids=None):
|
def idmaker(argnames, argvalues, idfn=None, ids=None, config=None):
|
||||||
ids = [_idvalset(valindex, valset, argnames, idfn, ids)
|
ids = [_idvalset(valindex, valset, argnames, idfn, ids, config)
|
||||||
for valindex, valset in enumerate(argvalues)]
|
for valindex, valset in enumerate(argvalues)]
|
||||||
if len(set(ids)) != len(ids):
|
if len(set(ids)) != len(ids):
|
||||||
# The ids are not unique
|
# The ids are not unique
|
||||||
|
|
|
@ -470,6 +470,7 @@ you can use the following hook:
|
||||||
|
|
||||||
.. autofunction:: pytest_pycollect_makeitem
|
.. autofunction:: pytest_pycollect_makeitem
|
||||||
.. autofunction:: pytest_generate_tests
|
.. autofunction:: pytest_generate_tests
|
||||||
|
.. autofunction:: pytest_make_parametrize_id
|
||||||
|
|
||||||
After collection is complete, you can modify the order of
|
After collection is complete, you can modify the order of
|
||||||
items, delete or otherwise amend the test items:
|
items, delete or otherwise amend the test items:
|
||||||
|
|
|
@ -1156,3 +1156,21 @@ class TestMarkersWithParametrization:
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=2)
|
reprec.assertoutcome(passed=2)
|
||||||
|
|
||||||
|
def test_pytest_make_parametrize_id(self, testdir):
|
||||||
|
testdir.makeconftest("""
|
||||||
|
def pytest_make_parametrize_id(config, val):
|
||||||
|
return str(val * 2)
|
||||||
|
""")
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("x", range(2))
|
||||||
|
def test_func(x):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest("-v")
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*test_func*0*PASS*",
|
||||||
|
"*test_func*2*PASS*",
|
||||||
|
])
|
||||||
|
|
Loading…
Reference in New Issue