Skip to content

Commit c581816

Browse files
committed
F6401 cannot-enumerate-pytest-fixtures (#16)
1 parent 5bde71e commit c581816

File tree

6 files changed

+59
-1
lines changed

6 files changed

+59
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
## Added
55
- W6402 `useless-pytest-mark-decorator`: add warning for [using pytest.mark on fixtures](https://docs.pytest.org/en/stable/reference.html#marks) (thanks to @DKorytkin)
66
- W6403 `deprecated-positional-argument-for-pytest-fixture`: add warning for [positional arguments to pytest.fixture()](https://docs.pytest.org/en/stable/deprecations.html#pytest-fixture-arguments-are-keyword-only) (thanks to @DKorytkin)
7+
- F6401 `cannot-enumerate-pytest-fixtures`: add fatal error when the plugin cannot enumerate and collect pytest fixtures for analysis (#27)
78

89
## [1.0.3] - 2021-03-13
910
## Fixed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ def awesome_fixture():
128128
...
129129
```
130130

131+
### F6401 `cannot-enumerate-pytest-fixtures`
132+
133+
Raise when the plugin cannot enumerate and collect pytest fixtures for analysis
134+
135+
```python
136+
import no_such_package # <- pylint-pytest plugin cannot enumerate and collect pytest fixtures
137+
```
138+
131139
## Changelog
132140

133141
See [CHANGELOG](CHANGELOG.md).

pylint_pytest/checkers/fixture.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@
1717

1818
class FixtureCollector:
1919
fixtures = {}
20+
errors = set()
2021

2122
def pytest_sessionfinish(self, session):
2223
# pylint: disable=protected-access
2324
self.fixtures = session._fixturemanager._arg2fixturedefs
2425

26+
def pytest_collectreport(self, report):
27+
if report.failed:
28+
self.errors.add(report)
29+
2530

2631
class FixtureChecker(BasePytestChecker):
2732
__implements__ = IAstroidChecker
@@ -44,6 +49,13 @@ class FixtureChecker(BasePytestChecker):
4449
'deprecated-positional-argument-for-pytest-fixture',
4550
'Pass scope as a kwarg, not positional arg, which is deprecated in future pytest.'
4651
'Take a look at: https://docs.pytest.org/en/stable/deprecations.html#pytest-fixture-arguments-are-keyword-only',
52+
'F6401': (
53+
(
54+
'pylint-pytest plugin cannot enumerate and collect pytest fixtures. '
55+
'Please run `pytest --fixtures --collect-only` and resolve any potential syntax error or package dependency issues'
56+
),
57+
'cannot-enumerate-pytest-fixtures',
58+
'Used when pylint-pytest has been unable to enumerate and collect pytest fixtures.',
4759
),
4860
}
4961

@@ -95,7 +107,7 @@ def visit_module(self, node):
95107
# save and restore sys.path to prevent pytest.main from altering it
96108
sys_path = sys.path.copy()
97109

98-
pytest.main(
110+
ret = pytest.main(
99111
[
100112
node.file, '--fixtures', '--collect-only',
101113
'--pythonwarnings=ignore:Module already imported:pytest.PytestWarning',
@@ -107,6 +119,9 @@ def visit_module(self, node):
107119
sys.path = sys_path
108120

109121
FixtureChecker._pytest_fixtures = fixture_collector.fixtures
122+
123+
if ret != pytest.ExitCode.OK or fixture_collector.errors:
124+
self.add_message('cannot-enumerate-pytest-fixtures', node=node)
110125
finally:
111126
# restore output devices
112127
sys.stdout, sys.stderr = stdout, stderr
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from no_such_package import fixture
2+
3+
4+
def test_something(fixture):
5+
pass
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import pytest
2+
import this_is_invalid # makes pytest fail
3+
4+
5+
@pytest.fixture
6+
def fixture():
7+
pass
8+
9+
def test_something(fixture):
10+
pass
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import pytest
2+
from pylint.checkers.variables import VariablesChecker
3+
from base_tester import BasePytestTester
4+
from pylint_pytest.checkers.fixture import FixtureChecker
5+
6+
7+
class TestCannotEnumerateFixtures(BasePytestTester):
8+
CHECKER_CLASS = FixtureChecker
9+
MSG_ID = 'cannot-enumerate-pytest-fixtures'
10+
11+
@pytest.mark.parametrize('enable_plugin', [True, False])
12+
def test_no_such_package(self, enable_plugin):
13+
self.run_linter(enable_plugin)
14+
self.verify_messages(1 if enable_plugin else 0)
15+
16+
@pytest.mark.parametrize('enable_plugin', [True, False])
17+
def test_import_corrupted_module(self, enable_plugin):
18+
self.run_linter(enable_plugin)
19+
self.verify_messages(1 if enable_plugin else 0)

0 commit comments

Comments
 (0)