Merge pull request #2468 from nicoddemus/collection-report-2464

Fix incorrect "collected items" report when specifying tests on the command-line
This commit is contained in:
Ronny Pfannschmidt 2017-06-14 10:57:57 +02:00 committed by GitHub
commit 4e57a39067
7 changed files with 34 additions and 11 deletions

View File

@ -763,7 +763,11 @@ class Session(FSCollector):
if not has_matched and len(rep.result) == 1 and x.name == "()": if not has_matched and len(rep.result) == 1 and x.name == "()":
nextnames.insert(0, name) nextnames.insert(0, name)
resultnodes.extend(self.matchnodes([x], nextnames)) resultnodes.extend(self.matchnodes([x], nextnames))
node.ihook.pytest_collectreport(report=rep) else:
# report collection failures here to avoid failing to run some test
# specified in the command line because the module could not be
# imported (#134)
node.ihook.pytest_collectreport(report=rep)
return resultnodes return resultnodes
def genitems(self, node): def genitems(self, node):

View File

@ -282,7 +282,7 @@ class TerminalReporter:
line = "collected " line = "collected "
else: else:
line = "collecting " line = "collecting "
line += str(self._numcollected) + " items" line += str(self._numcollected) + " item" + ('' if self._numcollected == 1 else 's')
if errors: if errors:
line += " / %d errors" % errors line += " / %d errors" % errors
if skipped: if skipped:

1
changelog/2464.bugfix Normal file
View File

@ -0,0 +1 @@
Fix incorrect "collected items" report when specifying tests on the command-line.

View File

@ -317,8 +317,8 @@ class TestGeneralUsage(object):
]) ])
assert 'sessionstarttime' not in result.stderr.str() assert 'sessionstarttime' not in result.stderr.str()
@pytest.mark.parametrize('lookfor', ['test_fun.py', 'test_fun.py::test_a']) @pytest.mark.parametrize('lookfor', ['test_fun.py::test_a'])
def test_issue134_report_syntaxerror_when_collecting_member(self, testdir, lookfor): def test_issue134_report_error_when_collecting_member(self, testdir, lookfor):
testdir.makepyfile(test_fun=""" testdir.makepyfile(test_fun="""
def test_a(): def test_a():
pass pass

View File

@ -369,6 +369,11 @@ class TestSession(object):
assert len(colitems) == 1 assert len(colitems) == 1
assert colitems[0].fspath == p assert colitems[0].fspath == p
def get_reported_items(self, hookrec):
"""Return pytest.Item instances reported by the pytest_collectreport hook"""
calls = hookrec.getcalls('pytest_collectreport')
return [x for call in calls for x in call.report.result
if isinstance(x, pytest.Item)]
def test_collect_protocol_single_function(self, testdir): def test_collect_protocol_single_function(self, testdir):
p = testdir.makepyfile("def test_func(): pass") p = testdir.makepyfile("def test_func(): pass")
@ -386,9 +391,10 @@ class TestSession(object):
("pytest_collectstart", "collector.fspath == p"), ("pytest_collectstart", "collector.fspath == p"),
("pytest_make_collect_report", "collector.fspath == p"), ("pytest_make_collect_report", "collector.fspath == p"),
("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_pycollect_makeitem", "name == 'test_func'"),
("pytest_collectreport", "report.nodeid.startswith(p.basename)"), ("pytest_collectreport", "report.result[0].name == 'test_func'"),
("pytest_collectreport", "report.nodeid == ''")
]) ])
# ensure we are reporting the collection of the single test item (#2464)
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_func']
def test_collect_protocol_method(self, testdir): def test_collect_protocol_method(self, testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
@ -407,6 +413,8 @@ class TestSession(object):
assert items[0].name == "test_method" assert items[0].name == "test_method"
newid = items[0].nodeid newid = items[0].nodeid
assert newid == normid assert newid == normid
# ensure we are reporting the collection of the single test item (#2464)
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
def test_collect_custom_nodes_multi_id(self, testdir): def test_collect_custom_nodes_multi_id(self, testdir):
p = testdir.makepyfile("def test_func(): pass") p = testdir.makepyfile("def test_func(): pass")
@ -436,9 +444,8 @@ class TestSession(object):
"collector.__class__.__name__ == 'Module'"), "collector.__class__.__name__ == 'Module'"),
("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_pycollect_makeitem", "name == 'test_func'"),
("pytest_collectreport", "report.nodeid.startswith(p.basename)"), ("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
#("pytest_collectreport",
# "report.fspath == %r" % str(rcol.fspath)),
]) ])
assert len(self.get_reported_items(hookrec)) == 2
def test_collect_subdir_event_ordering(self, testdir): def test_collect_subdir_event_ordering(self, testdir):
p = testdir.makepyfile("def test_func(): pass") p = testdir.makepyfile("def test_func(): pass")
@ -495,11 +502,13 @@ class TestSession(object):
def test_method(self): def test_method(self):
pass pass
""") """)
arg = p.basename + ("::TestClass::test_method") arg = p.basename + "::TestClass::test_method"
items, hookrec = testdir.inline_genitems(arg) items, hookrec = testdir.inline_genitems(arg)
assert len(items) == 1 assert len(items) == 1
item, = items item, = items
assert item.nodeid.endswith("TestClass::()::test_method") assert item.nodeid.endswith("TestClass::()::test_method")
# ensure we are reporting the collection of the single test item (#2464)
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
class Test_getinitialnodes(object): class Test_getinitialnodes(object):
def test_global_file(self, testdir, tmpdir): def test_global_file(self, testdir, tmpdir):

View File

@ -513,12 +513,12 @@ def test_pytest_no_tests_collected_exit_status(testdir):
assert 1 assert 1
""") """)
result = testdir.runpytest() result = testdir.runpytest()
result.stdout.fnmatch_lines('*collected 1 items*') result.stdout.fnmatch_lines('*collected 1 item*')
result.stdout.fnmatch_lines('*1 passed*') result.stdout.fnmatch_lines('*1 passed*')
assert result.ret == main.EXIT_OK assert result.ret == main.EXIT_OK
result = testdir.runpytest('-k nonmatch') result = testdir.runpytest('-k nonmatch')
result.stdout.fnmatch_lines('*collected 1 items*') result.stdout.fnmatch_lines('*collected 1 item*')
result.stdout.fnmatch_lines('*1 deselected*') result.stdout.fnmatch_lines('*1 deselected*')
assert result.ret == main.EXIT_NOTESTSCOLLECTED assert result.ret == main.EXIT_NOTESTSCOLLECTED

View File

@ -204,6 +204,15 @@ class TestTerminal(object):
assert result.ret == 2 assert result.ret == 2
result.stdout.fnmatch_lines(['*KeyboardInterrupt*']) result.stdout.fnmatch_lines(['*KeyboardInterrupt*'])
def test_collect_single_item(self, testdir):
"""Use singular 'item' when reporting a single test item"""
testdir.makepyfile("""
def test_foobar():
pass
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines(['collected 1 item'])
class TestCollectonly(object): class TestCollectonly(object):
def test_collectonly_basic(self, testdir): def test_collectonly_basic(self, testdir):