PY-61313: Use the module root as the working directory if the absence of an explicit test source directory

Merge-request: IJ-MR-155743
Merged-by: Egor Eliseev <Egor.Eliseev@jetbrains.com>

GitOrigin-RevId: 2d2c80a9f83be04c8b1383e9f74b4048b1d521b1
This commit is contained in:
Alex Grönholm
2025-02-22 06:17:23 +00:00
committed by intellij-monorepo-bot
parent 6b98a19d27
commit f821e02859
5 changed files with 44 additions and 3 deletions
@@ -59,6 +59,7 @@ import com.jetbrains.python.run.targetBasedConfiguration.TargetWithVariant
import com.jetbrains.python.run.targetBasedConfiguration.createRefactoringListenerIfPossible
import com.jetbrains.python.run.targetBasedConfiguration.targetAsPsiElement
import com.jetbrains.python.sdk.PythonSdkUtil
import com.jetbrains.python.sdk.baseDir
import com.jetbrains.python.testing.doctest.PythonDocTestUtil
import jetbrains.buildServer.messages.serviceMessages.ServiceMessage
import jetbrains.buildServer.messages.serviceMessages.TestStdErr
@@ -801,7 +802,7 @@ internal class PyTestsConfigurationProducer : AbstractPythonTestConfigurationPro
val module = configuration.module ?: return null
val elementFile = element.containingFile as? PyFile ?: return null
val workingDirectory = getDirectoryForFileToBeImportedFrom(elementFile) ?: return null
val workingDirectory = getDirectoryForFileToBeImportedFrom(elementFile, module) ?: return null
val context = QNameResolveContext(ModuleBasedContextAnchor(module),
evalContext = TypeEvalContext.userInitiated(configuration.project,
null),
@@ -814,7 +815,7 @@ internal class PyTestsConfigurationProducer : AbstractPythonTestConfigurationPro
val virtualFile = element.virtualFile
val workingDirectory: VirtualFile = when (element) {
is PyFile -> getDirectoryForFileToBeImportedFrom(element)?.virtualFile
is PyFile -> getDirectoryForFileToBeImportedFrom(element, configuration.module)?.virtualFile
is PsiDirectory -> virtualFile
else -> return null
} ?: return null
@@ -828,11 +829,15 @@ internal class PyTestsConfigurationProducer : AbstractPythonTestConfigurationPro
* Returns test root for this file. Either it is specified explicitly or calculated using following strategy:
* Inspect file relative imports, find farthest and return folder with imported file
*/
private fun getDirectoryForFileToBeImportedFrom(file: PyFile): PsiDirectory? {
private fun getDirectoryForFileToBeImportedFrom(file: PyFile, module: Module?): PsiDirectory? {
getExplicitlyConfiguredTestRoot(file)?.let {
return PsiManager.getInstance(file.project).findDirectory(it)
}
module?.baseDir?.let {
return file.manager.findDirectory(it)
}
val maxRelativeLevel = file.fromImports.map { it.relativeLevel }.maxOrNull() ?: 0
var elementFolder = file.parent ?: return null
for (i in 1..maxRelativeLevel) {
@@ -0,0 +1 @@
[tool.pytest.ini_options]
@@ -0,0 +1,6 @@
import pytest
@pytest.fixture
def myfixture():
return 42
@@ -0,0 +1,2 @@
def test_myfixture(myfixture):
assert myfixture == 42
@@ -33,6 +33,7 @@ import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.testing.*;
import com.jetbrains.python.tools.sdkTools.SdkCreationType;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.jdom.Element;
import org.jdom.JDOMException;
@@ -653,6 +654,32 @@ public final class PythonPyTestingTest extends PyEnvTestCase {
});
}
/**
* New configuration should have the module root as the working directory in the absence of an explicit test root
*/
@Test
public void testWorkDirIsModuleRoot() {
runPythonTest(new CreateConfigurationTestTask<>(getFrameworkId(), PyTestConfiguration.class) {
@NotNull
@Override
protected List<PsiElement> getPsiElementsToRightClickOn() {
myFixture.configureByFile("conftest_in_parent_dir/tests/subdir/test_test.py");
final PyFunction test = myFixture.findElementByText("test_myfixture", PyFunction.class);
assert test != null;
return Collections.singletonList(test);
}
@Override
protected void checkConfiguration(@NotNull PyTestConfiguration configuration, @NotNull PsiElement elementToRightClickOn) {
super.checkConfiguration(configuration, elementToRightClickOn);
final String moduleRoot = myFixture.getTempDirPath();
MatcherAssert.assertThat("Wrong configuration directory set on new config",
configuration.getWorkingDirectory(),
Matchers.equalTo(moduleRoot));
}
});
}
/**
* In case when workdir is not set we should use closest src
*/