Skip to content

Commit d169d77

Browse files
committed
feature: default behavior now is to ignore duplicate paths specified from the command line. Use --keep-duplicates to retain duplicate paths.
1 parent ae07985 commit d169d77

File tree

6 files changed

+70
-3
lines changed

6 files changed

+70
-3
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ Punyashloka Biswal
9494
Quentin Pradet
9595
Ralf Schmitt
9696
Raphael Pierzina
97+
Roberto Polli
9798
Roman Bolshakov
9899
Ronny Pfannschmidt
99100
Ross Lawley

CHANGELOG.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,10 @@ time or change existing behaviors in order to make them less surprising/more use
116116
fixtures and reports them;
117117
+ ``--setup-show``: performs normal test execution and additionally shows
118118
setup and teardown of fixtures;
119+
+ ``--skip-duplicates``: ignore duplicate tests, taking into account only
120+
the first one `#1609`_;
119121

120-
Thanks `@d6e`_, `@kvas-it`_, `@sallner`_ and `@omarkohl`_ for the PRs.
122+
Thanks `@d6e`_, `@kvas-it`_, `@sallner`_, `@ioggstream`_ and `@omarkohl`_ for the PRs.
121123

122124
* New cli flag ``--override-ini``/``-o``: overrides values from the ini file.
123125
For example: ``"-o xfail_strict=True"``'.
@@ -514,6 +516,7 @@ time or change existing behaviors in order to make them less surprising/more use
514516

515517
.. _`traceback style docs`: https://pytest.org/latest/usage.html#modifying-python-traceback-printing
516518

519+
.. _#1609: https://github.com/pytest-dev/pytest/issues/1609
517520
.. _#1422: https://github.com/pytest-dev/pytest/issues/1422
518521
.. _#1379: https://github.com/pytest-dev/pytest/issues/1379
519522
.. _#1366: https://github.com/pytest-dev/pytest/issues/1366
@@ -539,6 +542,7 @@ time or change existing behaviors in order to make them less surprising/more use
539542
.. _@rabbbit: https://github.com/rabbbit
540543
.. _@hackebrot: https://github.com/hackebrot
541544
.. _@pquentin: https://github.com/pquentin
545+
.. _@ioggstream: https://github.com/ioggstream
542546

543547
2.8.7
544548
=====

_pytest/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ def __init__(self):
155155
self._conftestpath2mod = {}
156156
self._confcutdir = None
157157
self._noconftest = False
158+
self._duplicatepaths = set()
158159

159160
self.add_hookspecs(_pytest.hookspec)
160161
self.register(self)

_pytest/main.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ def pytest_addoption(parser):
6363
group.addoption('--noconftest', action="store_true",
6464
dest="noconftest", default=False,
6565
help="Don't load any conftest.py files.")
66+
group.addoption('--keepduplicates', '--keep-duplicates', action="store_true",
67+
dest="keepduplicates", default=False,
68+
help="Skip duplicate tests.")
6669

6770
group = parser.getgroup("debugconfig",
6871
"test session debugging and configuration")
@@ -154,7 +157,25 @@ def pytest_ignore_collect(path, config):
154157
excludeopt = config.getoption("ignore")
155158
if excludeopt:
156159
ignore_paths.extend([py.path.local(x) for x in excludeopt])
157-
return path in ignore_paths
160+
161+
if path in ignore_paths:
162+
return True
163+
164+
# Skip duplicate paths.
165+
# TODO: is this called when specifying direct filenames
166+
# from command lines, eg.
167+
# py.test test_a.py test_b.py
168+
keepduplicates = config.getoption("keepduplicates")
169+
duplicate_paths = config.pluginmanager._duplicatepaths
170+
if not keepduplicates:
171+
if path in duplicate_paths:
172+
# TODO should we log this?
173+
return True
174+
else:
175+
duplicate_paths.add(path)
176+
177+
return False
178+
158179

159180
class FSHookProxy:
160181
def __init__(self, fspath, pm, remove_mods):

testing/python/collect.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,3 +1213,43 @@ def test_syntax_error_with_non_ascii_chars(testdir):
12131213
'*SyntaxError*',
12141214
'*1 error in*',
12151215
])
1216+
1217+
1218+
def test_skip_duplicates_by_default(testdir):
1219+
"""Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609)
1220+
1221+
Ignore duplicate directories.
1222+
"""
1223+
a = testdir.mkdir("a")
1224+
fh = a.join("test_a.py")
1225+
fh.write(_pytest._code.Source("""
1226+
import pytest
1227+
def test_real():
1228+
pass
1229+
"""))
1230+
result = testdir.runpytest(a.strpath, a.strpath)
1231+
result.stdout.fnmatch_lines([
1232+
'*collected 1 item*',
1233+
])
1234+
1235+
1236+
1237+
def test_keep_duplicates(testdir):
1238+
"""Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609)
1239+
1240+
Use --keep-duplicates to collect tests from duplicate directories.
1241+
"""
1242+
a = testdir.mkdir("a")
1243+
fh = a.join("test_a.py")
1244+
fh.write(_pytest._code.Source("""
1245+
import pytest
1246+
def test_real():
1247+
pass
1248+
"""))
1249+
result = testdir.runpytest("--keep-duplicates", a.strpath, a.strpath)
1250+
result.stdout.fnmatch_lines([
1251+
'*collected 2 item*',
1252+
])
1253+
1254+
1255+

testing/python/metafunc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ def pytest_generate_tests(metafunc):
939939
"""))
940940
sub1.join("test_in_sub1.py").write("def test_1(): pass")
941941
sub2.join("test_in_sub2.py").write("def test_2(): pass")
942-
result = testdir.runpytest("-v", "-s", sub1, sub2, sub1)
942+
result = testdir.runpytest("--keep-duplicates", "-v", "-s", sub1, sub2, sub1)
943943
result.assert_outcomes(passed=3)
944944

945945
def test_generate_same_function_names_issue403(self, testdir):

0 commit comments

Comments
 (0)