diff --git a/python/src/com/jetbrains/extenstions/QualifiedNameExt.kt b/python/src/com/jetbrains/extenstions/QualifiedNameExt.kt index 4ebd274fba17..76f160febdb8 100644 --- a/python/src/com/jetbrains/extenstions/QualifiedNameExt.kt +++ b/python/src/com/jetbrains/extenstions/QualifiedNameExt.kt @@ -62,8 +62,22 @@ fun QualifiedName.getRelativeNameTo(root: QualifiedName): QualifiedName? { /** * Resolves qname of any symbol to appropriate PSI element. + * Shortcut for [getElementAndResolvableName] + * @see [getElementAndResolvableName] */ fun QualifiedName.resolveToElement(context: QNameResolveContext): PsiElement? { + return getElementAndResolvableName(context)?.element +} + + +data class NameAndElement(val name:QualifiedName, val element:PsiElement) + +/** + * Resolves qname of any symbol to PSI element popping tail until element becomes resolved. + * @return element and longest name that was resolved successfully. + * @see [resolveToElement] + */ +fun QualifiedName.getElementAndResolvableName(context: QNameResolveContext): NameAndElement? { var currentName = QualifiedName.fromComponents(this.components) @@ -106,7 +120,7 @@ fun QualifiedName.resolveToElement(context: QNameResolveContext): PsiElement? { //TODO: Support nested classes val method = element.findMethodByName(lastElement, true, context.evalContext) if (method != null) { - return method + return NameAndElement(currentName.append(lastElement), method) } } @@ -122,7 +136,7 @@ fun QualifiedName.resolveToElement(context: QNameResolveContext): PsiElement? { } else { pyFile.virtualFile.parent } - return resolveToElement(context.copy(folderToStart = folder)) + return getElementAndResolvableName(context.copy(folderToStart = folder)) } - return element + return if (element != null) NameAndElement(currentName, element) else null } \ No newline at end of file diff --git a/python/src/com/jetbrains/python/testing/PyTestsShared.kt b/python/src/com/jetbrains/python/testing/PyTestsShared.kt index 7844044c850c..578a168567e2 100644 --- a/python/src/com/jetbrains/python/testing/PyTestsShared.kt +++ b/python/src/com/jetbrains/python/testing/PyTestsShared.kt @@ -23,6 +23,7 @@ import com.intellij.execution.testframework.AbstractTestProxy import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.psi.PsiElement import com.jetbrains.extensions.getQName +import com.jetbrains.extenstions.getElementAndResolvableName import com.jetbrains.extenstions.resolveToElement import com.jetbrains.python.psi.types.TypeEvalContext import com.jetbrains.python.run.PythonRunConfiguration @@ -230,8 +231,11 @@ data class ConfigurationTarget(@com.jetbrains.python.testing.ConfigField var tar // Try to set path relative to work dir (better than path from closest root) // If we can resolve element by this path relative to working directory then use it val qNameInsideOfDirectory = qualifiedNameParts.getElementNamePrependingFile() - if (qNameInsideOfDirectory.resolveToElement(qNameResolveContext.copy(allowInaccurateResult = false)) != null) { - return listOf("--target", qNameInsideOfDirectory.toString()) + val elementAndName = qNameInsideOfDirectory.getElementAndResolvableName(qNameResolveContext.copy(allowInaccurateResult = false)) + if (elementAndName != null) { + // qNameInsideOfDirectory may contain redundant elements like subtests so we use name that was really resolved + // element.qname can't be used because inherited test resolves to parent + return listOf("--target",elementAndName.name.toString()) } // Use "full" (path from closest root) otherwise val name = (element.containingFile as? com.jetbrains.python.psi.PyFile)?.getQName()?.append(qualifiedNameParts.elementName) ?: diff --git a/python/testSrc/com/jetbrains/env/python/testing/PyUnitTestProcessWithConsoleTestTask.java b/python/testSrc/com/jetbrains/env/python/testing/PyUnitTestProcessWithConsoleTestTask.java index 6e217b11a89f..5467db48f69b 100644 --- a/python/testSrc/com/jetbrains/env/python/testing/PyUnitTestProcessWithConsoleTestTask.java +++ b/python/testSrc/com/jetbrains/env/python/testing/PyUnitTestProcessWithConsoleTestTask.java @@ -45,10 +45,17 @@ import java.util.Set; abstract class PyUnitTestProcessWithConsoleTestTask extends PyProcessWithConsoleTestTask { @NotNull protected final String myScriptName; + private final int myRerunFailedTests; PyUnitTestProcessWithConsoleTestTask(@NotNull final String relativePathToTestData, @NotNull final String scriptName) { + this(relativePathToTestData, scriptName, 0); + } + PyUnitTestProcessWithConsoleTestTask(@NotNull final String relativePathToTestData, + @NotNull final String scriptName, + final int rerunFailedTests) { super(relativePathToTestData, SdkCreationType.SDK_PACKAGES_ONLY); myScriptName = scriptName; + myRerunFailedTests= rerunFailedTests; } @Nullable @@ -60,7 +67,7 @@ abstract class PyUnitTestProcessWithConsoleTestTask extends PyProcessWithConsole @NotNull @Override protected PyUnitTestProcessRunner createProcessRunner() throws Exception { - return new PyUnitTestProcessRunner(myScriptName, 0); + return new PyUnitTestProcessRunner(myScriptName, myRerunFailedTests); } diff --git a/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java b/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java index 4d1cffc38e30..07e89c02454e 100644 --- a/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java +++ b/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java @@ -141,7 +141,7 @@ public final class PythonUnitTestingTest extends PyEnvTestCase { @NotNull @Override protected PyUnitTestProcessRunner createProcessRunner() throws Exception { - return new PyUnitTestProcessRunner(toFullPath(myScriptName), 0); + return new PyUnitTestProcessRunner(toFullPath(myScriptName), 1); } @Override @@ -417,7 +417,7 @@ public final class PythonUnitTestingTest extends PyEnvTestCase { @EnvTestTagsRequired(tags = "python3") // No subtest in py2 @Test public void testSubtest() throws Exception { - runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/", "test_subtest.py") { + runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/", "test_subtest.py", 1) { @Override protected void checkTestResults(@NotNull PyUnitTestProcessRunner runner, @NotNull String stdout, @@ -446,7 +446,7 @@ public final class PythonUnitTestingTest extends PyEnvTestCase { @EnvTestTagsRequired(tags = "python3") // No subtest in py2 @Test public void testSubtestSkipped() throws Exception { - runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/", "test_skipped_subtest.py") { + runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/", "test_skipped_subtest.py", 1) { @Override protected void checkTestResults(@NotNull PyUnitTestProcessRunner runner, @NotNull String stdout,