diff --git a/.gitignore b/.gitignore index e4355b859..68e43d3f2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ env/ .coverage .ropeproject .idea +.hypothesis diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7bbfb4b0e..88dcb6e32 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,8 +29,11 @@ * parametrize ids can accept None as specific test id. The automatically generated id for that argument will be used. + Thanks `@palaviv`_ for the complete PR (`#1468`_). -* +* improved idmaker name selection in case of duplicate ids in + parametrize. + Thanks `@palaviv`_ for the complete PR (`#1474`_). * @@ -39,12 +42,15 @@ .. _@kalekundert: https://github.com/kalekundert .. _@tareqalayan: https://github.com/tareqalayan .. _@ceridwen: https://github.com/ceridwen +.. _@palaviv: https://github.com/palaviv .. _#1428: https://github.com/pytest-dev/pytest/pull/1428 .. _#1444: https://github.com/pytest-dev/pytest/pull/1444 .. _#1441: https://github.com/pytest-dev/pytest/pull/1441 .. _#1454: https://github.com/pytest-dev/pytest/pull/1454 .. _#1351: https://github.com/pytest-dev/pytest/issues/1351 +.. _#1468: https://github.com/pytest-dev/pytest/pull/1468 +.. _#1474: https://github.com/pytest-dev/pytest/pull/1474 2.9.2.dev1 ========== diff --git a/_pytest/python.py b/_pytest/python.py index 070c54715..6785892d9 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -7,6 +7,7 @@ import re import types import sys import math +import collections import py import pytest @@ -1161,9 +1162,14 @@ def _idvalset(idx, valset, argnames, idfn, ids): 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 - ids = [str(i) + testid for i, testid in enumerate(ids)] + if len(set(ids)) != len(ids): + # The ids are not unique + duplicates = [testid for testid in ids if ids.count(testid) > 1] + counters = collections.defaultdict(lambda: 0) + for index, testid in enumerate(ids): + if testid in duplicates: + ids[index] = testid + str(counters[testid]) + counters[testid] += 1 return ids def showfixtures(config): diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 59e05dd57..6ae3ca43f 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -254,9 +254,9 @@ class TestMetafunc: (20, KeyError()), ("three", [1, 2, 3]), ], idfn=ids) - assert result == ["0a-a", - "1a-a", - "2a-a", + assert result == ["a-a0", + "a-a1", + "a-a2", ] @pytest.mark.issue351 @@ -283,10 +283,9 @@ class TestMetafunc: 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"] + result = idmaker(("a"), [1,2,3,4,5], + ids=["a", "a", "b", "c", "b"]) + assert result == ["a0", "a1", "b0", "c", "b1"] def test_addcall_and_parametrize(self): def func(x, y): pass @@ -850,8 +849,8 @@ class TestMetafuncFunctional: result = testdir.runpytest("-v") assert result.ret == 1 result.stdout.fnmatch_lines_random([ - "*test_function*0a*PASSED", - "*test_function*1a*FAILED" + "*test_function*a0*PASSED", + "*test_function*a1*FAILED" ]) @pytest.mark.parametrize(("scope", "length"), diff --git a/tox.ini b/tox.ini index 0876f510c..ac604b88e 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,7 @@ deps= [testenv:py26] commands= py.test --lsof -rfsxX {posargs:testing} deps= - hypothesis<3.03 + hypothesis<3.0 nose mock<1.1 # last supported version for py26