Skip to content

Commit 74589b6

Browse files
authored
Merge pull request #15 from stdedos/fix/21-exclude-non-tests
See more details in #15
2 parents c84ad36 + b8f9dc4 commit 74589b6

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

pylint_pytest/checkers/fixture.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import fnmatch
2-
import os
2+
import io
33
import sys
44
from pathlib import Path
55
from typing import Set, Tuple
@@ -68,8 +68,8 @@ class FixtureChecker(BasePytestChecker):
6868
"F6401": (
6969
(
7070
"pylint-pytest plugin cannot enumerate and collect pytest fixtures. "
71-
"Please run `pytest --fixtures --collect-only path/to/current/module.py`"
72-
" and resolve any potential syntax error or package dependency issues"
71+
"Please run `pytest --fixtures --collect-only %s` and resolve "
72+
"any potential syntax error or package dependency issues. stdout: %s. stderr: %s."
7373
),
7474
"cannot-enumerate-pytest-fixtures",
7575
"Used when pylint-pytest has been unable to enumerate and collect pytest fixtures.",
@@ -118,9 +118,10 @@ def visit_module(self, node):
118118

119119
stdout, stderr = sys.stdout, sys.stderr
120120
try:
121-
with open(os.devnull, "w") as devnull:
121+
with io.StringIO() as captured_stdout, io.StringIO() as captured_stderr:
122122
# suppress any future output from pytest
123-
sys.stderr = sys.stdout = devnull
123+
sys.stderr = captured_stderr
124+
sys.stdout = captured_stdout
124125

125126
# run pytest session with customized plugin to collect fixtures
126127
fixture_collector = FixtureCollector()
@@ -143,8 +144,32 @@ def visit_module(self, node):
143144

144145
FixtureChecker._pytest_fixtures = fixture_collector.fixtures
145146

146-
if (ret != pytest.ExitCode.OK or fixture_collector.errors) and is_test_module:
147-
self.add_message("cannot-enumerate-pytest-fixtures", node=node)
147+
legitimate_failure_paths = set(
148+
collection_report.nodeid
149+
for collection_report in fixture_collector.errors
150+
if any(
151+
fnmatch.fnmatch(
152+
Path(collection_report.nodeid).name,
153+
pattern,
154+
)
155+
for pattern in FILE_NAME_PATTERNS
156+
)
157+
)
158+
if (ret != pytest.ExitCode.OK or legitimate_failure_paths) and is_test_module:
159+
files_to_report = {
160+
str(Path(x).absolute().relative_to(Path.cwd()))
161+
for x in legitimate_failure_paths | {node.file}
162+
}
163+
164+
self.add_message(
165+
"cannot-enumerate-pytest-fixtures",
166+
args=(
167+
" ".join(files_to_report),
168+
captured_stdout.getvalue(),
169+
captured_stderr.getvalue(),
170+
),
171+
node=node,
172+
)
148173
finally:
149174
# restore output devices
150175
sys.stdout, sys.stderr = stdout, stderr

tests/test_cannot_enumerate_fixtures.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
13
import pytest
24
from base_tester import BasePytestTester
35

@@ -13,7 +15,39 @@ def test_no_such_package(self, enable_plugin):
1315
self.run_linter(enable_plugin)
1416
self.verify_messages(1 if enable_plugin else 0)
1517

18+
if enable_plugin:
19+
msg = self.msgs[0]
20+
21+
# Asserts/Fixes duplicate filenames in output:
22+
# https://github.com/reverbc/pylint-pytest/pull/22/files#r698204470
23+
filename_arg = msg.args[0]
24+
assert len(re.findall(r"\.py", filename_arg)) == 1
25+
26+
# Asserts that path is relative (usually to the root of the repository).
27+
assert filename_arg[0] != "/"
28+
29+
# Assert `stdout` is non-empty.
30+
assert msg.args[1]
31+
# Assert `stderr` is empty (pytest runs stably, even though fixture collection fails).
32+
assert not msg.args[2]
33+
1634
@pytest.mark.parametrize("enable_plugin", [True, False])
1735
def test_import_corrupted_module(self, enable_plugin):
1836
self.run_linter(enable_plugin)
1937
self.verify_messages(1 if enable_plugin else 0)
38+
39+
if enable_plugin:
40+
msg = self.msgs[0]
41+
42+
# ... somehow, since `import_corrupted_module.py` imports `no_such_package.py`
43+
# both of their names are returned in the message.
44+
filename_arg = msg.args[0]
45+
assert len(re.findall(r"\.py", filename_arg)) == 2
46+
47+
# Asserts that paths are relative (usually to the root of the repository).
48+
assert not [x for x in filename_arg.split(" ") if x[0] == "/"]
49+
50+
# Assert `stdout` is non-empty.
51+
assert msg.args[1]
52+
# Assert `stderr` is empty (pytest runs stably, even though fixture collection fails).
53+
assert not msg.args[2]

0 commit comments

Comments
 (0)