Skip to content

Commit 4e57a39

Browse files
Merge pull request #2468 from nicoddemus/collection-report-2464
Fix incorrect "collected items" report when specifying tests on the command-line
2 parents af0344e + 46d157f commit 4e57a39

File tree

7 files changed

+34
-11
lines changed

7 files changed

+34
-11
lines changed

_pytest/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,11 @@ def _matchnodes(self, matching, names):
763763
if not has_matched and len(rep.result) == 1 and x.name == "()":
764764
nextnames.insert(0, name)
765765
resultnodes.extend(self.matchnodes([x], nextnames))
766-
node.ihook.pytest_collectreport(report=rep)
766+
else:
767+
# report collection failures here to avoid failing to run some test
768+
# specified in the command line because the module could not be
769+
# imported (#134)
770+
node.ihook.pytest_collectreport(report=rep)
767771
return resultnodes
768772

769773
def genitems(self, node):

_pytest/terminal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def report_collect(self, final=False):
282282
line = "collected "
283283
else:
284284
line = "collecting "
285-
line += str(self._numcollected) + " items"
285+
line += str(self._numcollected) + " item" + ('' if self._numcollected == 1 else 's')
286286
if errors:
287287
line += " / %d errors" % errors
288288
if skipped:

changelog/2464.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix incorrect "collected items" report when specifying tests on the command-line.

testing/acceptance_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ def pytest_configure():
317317
])
318318
assert 'sessionstarttime' not in result.stderr.str()
319319

320-
@pytest.mark.parametrize('lookfor', ['test_fun.py', 'test_fun.py::test_a'])
321-
def test_issue134_report_syntaxerror_when_collecting_member(self, testdir, lookfor):
320+
@pytest.mark.parametrize('lookfor', ['test_fun.py::test_a'])
321+
def test_issue134_report_error_when_collecting_member(self, testdir, lookfor):
322322
testdir.makepyfile(test_fun="""
323323
def test_a():
324324
pass

testing/test_collection.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@ def test_collect_topdir(self, testdir):
369369
assert len(colitems) == 1
370370
assert colitems[0].fspath == p
371371

372+
def get_reported_items(self, hookrec):
373+
"""Return pytest.Item instances reported by the pytest_collectreport hook"""
374+
calls = hookrec.getcalls('pytest_collectreport')
375+
return [x for call in calls for x in call.report.result
376+
if isinstance(x, pytest.Item)]
372377

373378
def test_collect_protocol_single_function(self, testdir):
374379
p = testdir.makepyfile("def test_func(): pass")
@@ -386,9 +391,10 @@ def test_collect_protocol_single_function(self, testdir):
386391
("pytest_collectstart", "collector.fspath == p"),
387392
("pytest_make_collect_report", "collector.fspath == p"),
388393
("pytest_pycollect_makeitem", "name == 'test_func'"),
389-
("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
390-
("pytest_collectreport", "report.nodeid == ''")
394+
("pytest_collectreport", "report.result[0].name == 'test_func'"),
391395
])
396+
# ensure we are reporting the collection of the single test item (#2464)
397+
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_func']
392398

393399
def test_collect_protocol_method(self, testdir):
394400
p = testdir.makepyfile("""
@@ -407,6 +413,8 @@ def test_method(self):
407413
assert items[0].name == "test_method"
408414
newid = items[0].nodeid
409415
assert newid == normid
416+
# ensure we are reporting the collection of the single test item (#2464)
417+
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
410418

411419
def test_collect_custom_nodes_multi_id(self, testdir):
412420
p = testdir.makepyfile("def test_func(): pass")
@@ -436,9 +444,8 @@ def pytest_collect_file(path, parent):
436444
"collector.__class__.__name__ == 'Module'"),
437445
("pytest_pycollect_makeitem", "name == 'test_func'"),
438446
("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
439-
#("pytest_collectreport",
440-
# "report.fspath == %r" % str(rcol.fspath)),
441447
])
448+
assert len(self.get_reported_items(hookrec)) == 2
442449

443450
def test_collect_subdir_event_ordering(self, testdir):
444451
p = testdir.makepyfile("def test_func(): pass")
@@ -495,11 +502,13 @@ class TestClass(object):
495502
def test_method(self):
496503
pass
497504
""")
498-
arg = p.basename + ("::TestClass::test_method")
505+
arg = p.basename + "::TestClass::test_method"
499506
items, hookrec = testdir.inline_genitems(arg)
500507
assert len(items) == 1
501508
item, = items
502509
assert item.nodeid.endswith("TestClass::()::test_method")
510+
# ensure we are reporting the collection of the single test item (#2464)
511+
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
503512

504513
class Test_getinitialnodes(object):
505514
def test_global_file(self, testdir, tmpdir):

testing/test_runner.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,12 +513,12 @@ def test_foo():
513513
assert 1
514514
""")
515515
result = testdir.runpytest()
516-
result.stdout.fnmatch_lines('*collected 1 items*')
516+
result.stdout.fnmatch_lines('*collected 1 item*')
517517
result.stdout.fnmatch_lines('*1 passed*')
518518
assert result.ret == main.EXIT_OK
519519

520520
result = testdir.runpytest('-k nonmatch')
521-
result.stdout.fnmatch_lines('*collected 1 items*')
521+
result.stdout.fnmatch_lines('*collected 1 item*')
522522
result.stdout.fnmatch_lines('*1 deselected*')
523523
assert result.ret == main.EXIT_NOTESTSCOLLECTED
524524

testing/test_terminal.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,15 @@ def test_foobar():
204204
assert result.ret == 2
205205
result.stdout.fnmatch_lines(['*KeyboardInterrupt*'])
206206

207+
def test_collect_single_item(self, testdir):
208+
"""Use singular 'item' when reporting a single test item"""
209+
testdir.makepyfile("""
210+
def test_foobar():
211+
pass
212+
""")
213+
result = testdir.runpytest()
214+
result.stdout.fnmatch_lines(['collected 1 item'])
215+
207216

208217
class TestCollectonly(object):
209218
def test_collectonly_basic(self, testdir):

0 commit comments

Comments
 (0)