Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

None in paramtrized test id will use automatically generated id #1468

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

**Changes**

*
* parametrize ids can accept None as specific test id. The
automatically generated id for that argument will be used.

*

Expand All @@ -45,7 +46,7 @@

**Bug Fixes**

*
* When receiving identical test ids in parametrize we generate unique test ids.

*

Expand Down
21 changes: 12 additions & 9 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,8 @@ def parametrize(self, argnames, argvalues, indirect=False, ids=None,

:arg ids: list of string ids, or a callable.
If strings, each is corresponding to the argvalues so that they are
part of the test id.
part of the test id. If None is given as id of specific test, the
automatically generated id for that argument will be used.
If callable, it should take one argument (a single argvalue) and return
a string or return None. If None, the automatically generated id for that
argument will be used.
Expand Down Expand Up @@ -1028,8 +1029,7 @@ def parametrize(self, argnames, argvalues, indirect=False, ids=None,
if ids and len(ids) != len(argvalues):
raise ValueError('%d tests specified with %d ids' %(
len(argvalues), len(ids)))
if not ids:
ids = idmaker(argnames, argvalues, idfn)
ids = idmaker(argnames, argvalues, idfn, ids)
newcalls = []
for callspec in self._calls or [CallSpec2(self)]:
for param_index, valset in enumerate(argvalues):
Expand Down Expand Up @@ -1141,13 +1141,16 @@ def _idval(val, argname, idx, idfn):
pass
return str(argname)+str(idx)

def _idvalset(idx, valset, argnames, idfn):
this_id = [_idval(val, argname, idx, idfn)
for val, argname in zip(valset, argnames)]
return "-".join(this_id)
def _idvalset(idx, valset, argnames, idfn, ids):
if ids is None or ids[idx] is None:
this_id = [_idval(val, argname, idx, idfn)
for val, argname in zip(valset, argnames)]
return "-".join(this_id)
else:
return ids[idx]

def idmaker(argnames, argvalues, idfn=None):
ids = [_idvalset(valindex, valset, argnames, idfn)
def idmaker(argnames, argvalues, idfn=None, ids=None):
ids = [_idvalset(valindex, valset, argnames, idfn, ids)
for valindex, valset in enumerate(argvalues)]
if len(set(ids)) < len(ids):
# user may have provided a bad idfn which means the ids are not unique
Expand Down
49 changes: 49 additions & 0 deletions testing/python/metafunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,20 @@ def ids(val):
"three-b2",
]

def test_idmaker_with_ids(self):
from _pytest.python import idmaker
result = idmaker(("a", "b"), [(1, 2),
(3, 4)],
ids=["a", None])
assert result == ["a", "3-4"]

def test_idmaker_with_ids_unique_names(self):
from _pytest.python import idmaker
result = idmaker(("a", "b"), [(1, 2),
(3, 4)],
ids=["a", "a"])
assert result == ["0a", "1a"]

def test_addcall_and_parametrize(self):
def func(x, y): pass
metafunc = self.Metafunc(func)
Expand Down Expand Up @@ -789,6 +803,41 @@ def test_function(a, b):
*test_function*1.3-b1*
""")

def test_parametrize_with_None_in_ids(self, testdir):
testdir.makepyfile("""
import pytest
def pytest_generate_tests(metafunc):
metafunc.parametrize(("a", "b"), [(1,1), (1,1), (1,2)],
ids=["basic", None, "advanced"])

def test_function(a, b):
assert a == b
""")
result = testdir.runpytest("-v")
assert result.ret == 1
result.stdout.fnmatch_lines_random([
"*test_function*basic*PASSED",
"*test_function*1-1*PASSED",
"*test_function*advanced*FAILED",
])

def test_parametrize_with_identical_ids_get_unique_names(self, testdir):
testdir.makepyfile("""
import pytest
def pytest_generate_tests(metafunc):
metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
ids=["a", "a"])

def test_function(a, b):
assert a == b
""")
result = testdir.runpytest("-v")
assert result.ret == 1
result.stdout.fnmatch_lines_random([
"*test_function*0a*PASSED",
"*test_function*1a*FAILED"
])

@pytest.mark.parametrize(("scope", "length"),
[("module", 2), ("function", 4)])
def test_parametrize_scope_overrides(self, testdir, scope, length):
Expand Down