mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
PY-71370: Resolve any suitable fixture candidate if pytest_plugins cannot be parsed
This bug was introduced during a refactoring of fixture support.
While the correct order of resolution was maintained, it relied on the assumption that pytest_plugins could be statically analyzed.
Consider the following example:
```python
import os
from glob import iglob
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
def create_pytest_plugins():
# Dynamically resolves fixture plugin names by scanning the fixtures directory
fixture_names = _make_fixture_names("tests/utils/fixtures/**/*.py")
return fixture_names
def _make_fixture_names(fixture_path_pattern: str):
os.chdir(f"{DIR_PATH}/../../")
return [
_make_fixture_name(fixture_path)
for fixture_path in iglob(fixture_path_pattern, recursive=True)
if "__" not in fixture_path
]
def _make_fixture_name(fixture_path: str) -> str:
return fixture_path.replace("/", ".").replace(".py", "")
pytest_plugins = create_pytest_plugins()
```
In such cases, where pytest_plugins is resolved dynamically and cannot be parsed statically, it is preferable to fall back to resolving any other suitable fixture found in the project, rather than skipping resolution altogether.
(cherry picked from commit 2d9a5dd6bd34d1c06d47b3587cd365696642ccd7)
IJ-MR-167570
GitOrigin-RevId: 709f080d6c23d1f76ad397cb6363e74623758cfd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3e84f70fa3
commit
a73bbf2a4d
@@ -274,7 +274,12 @@ private fun getFixtureFromPytestPlugins(targetFile: PyFile, fixtureCandidates: L
|
||||
is PyParenthesizedExpression -> assignedValue.children.find { it is PyTupleExpression }?.let { tuple ->
|
||||
(tuple as PyTupleExpression).elements.mapNotNull { resolve(it) }
|
||||
} ?: emptyList()
|
||||
else -> emptyList()
|
||||
else -> {
|
||||
// `pytest_plugins` is not parsable, most likely looks like `pytest_plugins = create_pytest_plugins()`
|
||||
// In that case it is better to return any suitable fixtureCandidate
|
||||
val candidate = fixtureCandidates.firstOrNull() ?: return null
|
||||
return NamedFixtureLink(candidate, null)
|
||||
}
|
||||
}
|
||||
|
||||
if (fixtures.isEmpty()) return null
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
def calculate_fixtures():
|
||||
# Imitate custom logic around collecting folders.
|
||||
# For the real-world examples see PY-71370
|
||||
fixtures_folder = "fixtures"
|
||||
subdirectories = ["first", "second"]
|
||||
return [f"{fixtures_folder}.{subdir}" for subdir in subdirectories]
|
||||
|
||||
|
||||
pytest_plugins = calculate_fixtures()
|
||||
@@ -0,0 +1,5 @@
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def first():
|
||||
return 1
|
||||
@@ -0,0 +1,5 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_first(fi<caret>rst):
|
||||
assert first == 1
|
||||
@@ -70,6 +70,7 @@ class PyTestFixtureResolvingTest : PyTestCase() {
|
||||
const val PYTEST_PLUGINS_FIXTURES_AS_STR_DIR = "/pytest_plugins_as_str"
|
||||
const val PYTEST_PLUGINS_FIXTURES_AS_TUPLE_DIR = "/pytest_plugins_as_tuple"
|
||||
const val PYTEST_PLUGINS_FIXTURES_AS_REF_DIR = "/pytest_plugins_as_ref"
|
||||
const val PYTEST_PLUGINS_FIXTURES_NOT_PARSABLE_DIR = "/pytest_plugins_not_parsable"
|
||||
const val PYTEST_PLUGINS_FIXTURES = "fixtures"
|
||||
const val PYTEST_PLUGINS_FIXTURES_FIRST = "first.py"
|
||||
const val PYTEST_PLUGINS_FIXTURES_SECOND = "second.py"
|
||||
@@ -79,6 +80,7 @@ class PyTestFixtureResolvingTest : PyTestCase() {
|
||||
const val PYTEST_PLUGINS_FIXTURES_AS_TUPLE_SECOND_TEST = "/test_pytest_plugins_as_tuple_second.py"
|
||||
const val PYTEST_PLUGINS_FIXTURES_AS_STR_TEST = "/test_pytest_plugins_as_str.py"
|
||||
const val PYTEST_PLUGINS_FIXTURES_AS_REF_TEST = "/test_pytest_plugins_as_ref.py"
|
||||
const val PYTEST_PLUGINS_FIXTURES_NOT_PARSABLE_TEST = "/test_pytest_plugins_not_parsable.py"
|
||||
|
||||
const val IMPORT_WITH_WILDCARD_DIR_NAME = "testImportWithWildcard"
|
||||
const val IMPORT_WITH_WILDCARD_DIR = "/$IMPORT_WITH_WILDCARD_DIR_NAME"
|
||||
@@ -304,6 +306,11 @@ class PyTestFixtureResolvingTest : PyTestCase() {
|
||||
assertCorrectFile(testDir, PYTEST_PLUGINS_FIXTURES_AS_REF_TEST, PYTEST_PLUGINS_FIXTURES_FIRST, PYTEST_PLUGINS_FIXTURES)
|
||||
}
|
||||
|
||||
fun testPytestPluginsFixtureNotParsable() {
|
||||
val testDir = PYTEST_PLUGINS_FIXTURES_DIR + PYTEST_PLUGINS_FIXTURES_NOT_PARSABLE_DIR
|
||||
assertCorrectFile(testDir, PYTEST_PLUGINS_FIXTURES_NOT_PARSABLE_TEST, PYTEST_PLUGINS_FIXTURES_FIRST, PYTEST_PLUGINS_FIXTURES)
|
||||
}
|
||||
|
||||
fun testImportWithWildCardFromInit() {
|
||||
val testDir = IMPORT_WITH_WILDCARD_DIR + IMPORT_WITH_WILDCARD_FROM_INIT_DIR
|
||||
assertCorrectFile(testDir, IMPORT_WITH_WILDCARD_TEST_FILE, IMPORT_WITH_WILDCARD_FIXTURES_FILE, IMPORT_WITH_WILDCARD_FIXTURES_DIR)
|
||||
|
||||
Reference in New Issue
Block a user