diff --git a/CHANGELOG b/CHANGELOG index 24ea1d87b..78a3a76d8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Changes between 2.2.4 and 2.3.0.dev ----------------------------------- +- fix issue202 - better automatic names for parametrized test functions - fix issue139 - introduce @pytest.fixture which allows direct scoping and parametrization of funcarg factories. Introduce new @pytest.setup marker to allow the writing of setup functions which accept funcargs. diff --git a/_pytest/__init__.py b/_pytest/__init__.py index 7a2224b6b..06f440563 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.3.0.dev31' +__version__ = '2.3.0.dev32' diff --git a/_pytest/python.py b/_pytest/python.py index 808ff487e..744c182c4 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -660,8 +660,7 @@ class Metafunc(FuncargnamesCompatAttr): self.function, arg)) valtype = indirect and "params" or "funcargs" if not ids: - idmaker = IDMaker() - ids = list(map(idmaker, argvalues)) + ids = idmaker(argnames, argvalues) newcalls = [] for callspec in self._calls or [CallSpec2(self)]: for i, valset in enumerate(argvalues): @@ -708,18 +707,17 @@ class Metafunc(FuncargnamesCompatAttr): cs.setall(funcargs, id, param) self._calls.append(cs) -class IDMaker: - def __init__(self): - self.counter = 0 - def __call__(self, valset): - l = [] - for val in valset: - if not isinstance(val, (int, str)): - val = "."+str(self.counter) - self.counter += 1 - l.append(str(val)) - return "-".join(l) - +def idmaker(argnames, argvalues): + idlist = [] + for valindex, valset in enumerate(argvalues): + this_id = [] + for nameindex, val in enumerate(valset): + if not isinstance(val, (float, int, str)): + this_id.append(argnames[nameindex]+str(valindex)) + else: + this_id.append(str(val)) + idlist.append("-".join(this_id)) + return idlist def showfixtures(config): from _pytest.main import wrap_session diff --git a/setup.py b/setup.py index e6c6c9019..5cf3c4e59 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ def main(): name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.3.0.dev31', + version='2.3.0.dev32', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff --git a/testing/test_python.py b/testing/test_python.py index 4912ebafb..cec277cfb 100644 --- a/testing/test_python.py +++ b/testing/test_python.py @@ -992,10 +992,21 @@ class TestMetafunc: pass metafunc.parametrize("x", [A(), A()]) metafunc.parametrize("y", list("ab")) - assert metafunc._calls[0].id == ".0-a" - assert metafunc._calls[1].id == ".0-b" - assert metafunc._calls[2].id == ".1-a" - assert metafunc._calls[3].id == ".1-b" + assert metafunc._calls[0].id == "x0-a" + assert metafunc._calls[1].id == "x0-b" + assert metafunc._calls[2].id == "x1-a" + assert metafunc._calls[3].id == "x1-b" + + def test_idmaker_autoname(self): + from _pytest.python import idmaker + result = idmaker(("a", "b"), [("string", 1.0), + ("st-ring", 2.0)]) + assert result == ["string-1.0", "st-ring-2.0"] + + result = idmaker(("a", "b"), [(object(), 1.0), + (object(), object())]) + assert result == ["a0-1.0", "a1-b1"] + def test_addcall_and_parametrize(self): def func(x, y): pass @@ -1362,6 +1373,41 @@ class TestMetafuncFunctional: "*1 passed*" ]) + def test_parametrize_with_ids(self, testdir): + testdir.makepyfile(""" + import pytest + def pytest_generate_tests(metafunc): + metafunc.parametrize(("a", "b"), [(1,1), (1,2)], + ids=["basic", "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*advanced*FAILED", + ]) + + def test_parametrize_without_ids(self, testdir): + testdir.makepyfile(""" + import pytest + def pytest_generate_tests(metafunc): + metafunc.parametrize(("a", "b"), + [(1,object()), (1.3,object())]) + + def test_function(a, b): + assert 1 + """) + result = testdir.runpytest("-v") + result.stdout.fnmatch_lines(""" + *test_function*1-b0* + *test_function*1.3-b1* + """) + + + @pytest.mark.parametrize(("scope", "length"), [("module", 2), ("function", 4)]) def test_parametrize_scope_overrides(self, testdir, scope, length): @@ -1985,24 +2031,6 @@ class TestFixtureUsages: reprec = testdir.inline_run() reprec.assertoutcome(passed=2) -class TestResourceIntegrationFunctional: - def test_parametrize_with_ids(self, testdir): - testdir.makepyfile(""" - import pytest - def pytest_generate_tests(metafunc): - metafunc.parametrize(("a", "b"), [(1,1), (1,2)], - ids=["basic", "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*advanced*FAILED", - ]) - class TestFixtureManager: def pytest_funcarg__testdir(self, request): testdir = request.getfuncargvalue("testdir")