From 87e4a28351ac372f553b9fe588da37cb35aa1b81 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 3 Jun 2017 18:26:34 -0300 Subject: [PATCH] Fix incorrect collected items report when specifying tests on the command-line Fix #2464 --- _pytest/main.py | 6 +++++- changelog/2464.bugfix | 1 + testing/acceptance_test.py | 4 ++-- testing/test_collection.py | 19 ++++++++++++++----- 4 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 changelog/2464.bugfix diff --git a/_pytest/main.py b/_pytest/main.py index 480810cc8..ec4ec2cc7 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -763,7 +763,11 @@ class Session(FSCollector): if not has_matched and len(rep.result) == 1 and x.name == "()": nextnames.insert(0, name) 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 def genitems(self, node): diff --git a/changelog/2464.bugfix b/changelog/2464.bugfix new file mode 100644 index 000000000..12062fd9e --- /dev/null +++ b/changelog/2464.bugfix @@ -0,0 +1 @@ +Fix incorrect "collected items" report when specifying tests on the command-line. diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 00abfc38d..9cb2650de 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -317,8 +317,8 @@ class TestGeneralUsage(object): ]) assert 'sessionstarttime' not in result.stderr.str() - @pytest.mark.parametrize('lookfor', ['test_fun.py', 'test_fun.py::test_a']) - def test_issue134_report_syntaxerror_when_collecting_member(self, testdir, lookfor): + @pytest.mark.parametrize('lookfor', ['test_fun.py::test_a']) + def test_issue134_report_error_when_collecting_member(self, testdir, lookfor): testdir.makepyfile(test_fun=""" def test_a(): pass diff --git a/testing/test_collection.py b/testing/test_collection.py index c19fc0e72..a90269789 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -369,6 +369,11 @@ class TestSession(object): assert len(colitems) == 1 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): p = testdir.makepyfile("def test_func(): pass") @@ -386,9 +391,10 @@ class TestSession(object): ("pytest_collectstart", "collector.fspath == p"), ("pytest_make_collect_report", "collector.fspath == p"), ("pytest_pycollect_makeitem", "name == 'test_func'"), - ("pytest_collectreport", "report.nodeid.startswith(p.basename)"), - ("pytest_collectreport", "report.nodeid == ''") + ("pytest_collectreport", "report.result[0].name == 'test_func'"), ]) + # 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): p = testdir.makepyfile(""" @@ -407,6 +413,8 @@ class TestSession(object): assert items[0].name == "test_method" newid = items[0].nodeid 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): p = testdir.makepyfile("def test_func(): pass") @@ -436,9 +444,8 @@ class TestSession(object): "collector.__class__.__name__ == 'Module'"), ("pytest_pycollect_makeitem", "name == 'test_func'"), ("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): p = testdir.makepyfile("def test_func(): pass") @@ -495,11 +502,13 @@ class TestSession(object): def test_method(self): pass """) - arg = p.basename + ("::TestClass::test_method") + arg = p.basename + "::TestClass::test_method" items, hookrec = testdir.inline_genitems(arg) assert len(items) == 1 item, = items 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): def test_global_file(self, testdir, tmpdir):