fixed PY-11617 Nosetest runner: simple function tests cannot jump to source

This commit is contained in:
Ekaterina Tuzova
2013-12-17 17:51:10 +04:00
parent 293de59bf5
commit a239ed4396
5 changed files with 151 additions and 52 deletions
+3 -3
View File
@@ -107,7 +107,7 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult):
location = location + ":" + str(test.test.lineno)
else:
suite = strclass(test.__class__)
suite_location = "python_uttestid://" + suite
suite_location = "python_nosetestid://" + suite
try:
from nose_helper.util import func_lineno
@@ -124,8 +124,8 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult):
except:
test_id = test.id()
suite_id = test_id[:test_id.rfind(".")]
suite_location = "python_uttestid://" + str(suite_id)
location = "python_uttestid://" + str(test_id)
suite_location = "python_nosetestid://" + str(suite_id)
location = "python_nosetestid://" + str(test_id)
return (location, suite_location)
+1
View File
@@ -114,6 +114,7 @@
<runConfigurationProducer implementation="com.jetbrains.python.testing.unittest.PythonUnitTestConfigurationProducer"/>
<testSrcLocator implementation="com.jetbrains.python.testing.PythonUnitTestTestIdUrlProvider"/>
<testSrcLocator implementation="com.jetbrains.python.testing.nosetest.PythonNoseTestUrlProvider"/>
<runConfigurationProducer implementation="com.jetbrains.python.testing.pytest.PyTestConfigurationProducer"/>
<runConfigurationProducer implementation="com.jetbrains.python.testing.doctest.PythonDocTestConfigurationProducer"/>
@@ -16,22 +16,12 @@
package com.jetbrains.python.testing;
import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.testIntegration.TestLocationProvider;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -55,55 +45,20 @@ public class PythonUnitTestTestIdUrlProvider implements TestLocationProvider {
// parse path as [ns.]*fileName.className[.methodName]
if (listSize == 2) {
return findLocations(project, list.get(0), list.get(1), null);
return PythonUnitTestUtil.findLocations(project, list.get(0), list.get(1), null);
}
if (listSize > 2) {
final String className = list.get(listSize - 2);
final String methodName = list.get(listSize - 1);
String fileName = list.get(listSize - 3);
final List<Location> locations = findLocations(project, fileName, className, methodName);
final List<Location> locations = PythonUnitTestUtil.findLocations(project, fileName, className, methodName);
if (locations.size() > 0) {
return locations;
}
return findLocations(project, list.get(listSize-2), list.get(listSize-1), null);
return PythonUnitTestUtil.findLocations(project, list.get(listSize-2), list.get(listSize-1), null);
}
return Collections.emptyList();
}
private static List<Location> findLocations(Project project,
String fileName,
String className,
@Nullable String methodName) {
if (fileName.indexOf("%") >= 0) {
fileName = fileName.substring(0, fileName.lastIndexOf("%"));
}
final List<Location> locations = new ArrayList<Location>();
for (PyClass cls : PyClassNameIndex.find(className, project, false)) {
ProgressManager.checkCanceled();
final PsiFile containingFile = cls.getContainingFile();
final VirtualFile virtualFile = containingFile.getVirtualFile();
final String clsFileName = virtualFile == null? containingFile.getName() : virtualFile.getPath();
final String clsFileNameWithoutExt = FileUtil.getNameWithoutExtension(clsFileName);
if (!clsFileNameWithoutExt.endsWith(fileName)) {
continue;
}
if (methodName == null) {
locations.add(new PsiLocation<PyClass>(project, cls));
}
else {
final PyFunction method = cls.findMethodByName(methodName, true);
if (method == null) {
continue;
}
locations.add(new PsiLocation<PyFunction>(project, method));
}
}
return locations;
}
}
@@ -17,14 +17,25 @@ package com.jetbrains.python.testing;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.containers.Stack;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.regex.Pattern;
@@ -148,7 +159,9 @@ public class PythonUnitTestUtil {
return true;
}
String clsName = cls.getQualifiedName();
String[] names = clsName.split("\\.");
String[] names = new String[0];
if (clsName != null)
names = clsName.split("\\.");
clsName = names[names.length - 1];
if (TEST_MATCH_PATTERN.matcher(clsName).find()) {
return true;
@@ -157,4 +170,62 @@ public class PythonUnitTestUtil {
}
return false;
}
public static List<Location> findLocations(@NotNull final Project project,
@NotNull String fileName,
@Nullable String className,
@Nullable String methodName) {
if (fileName.contains("%")) {
fileName = fileName.substring(0, fileName.lastIndexOf("%"));
}
final List<Location> locations = new ArrayList<Location>();
if (methodName == null && className == null) {
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(fileName);
if (virtualFile == null) return locations;
final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
if (psiFile != null)
locations.add(new PsiLocation<PsiFile>(project, psiFile));
}
if (className != null) {
for (PyClass cls : PyClassNameIndex.find(className, project, false)) {
ProgressManager.checkCanceled();
final PsiFile containingFile = cls.getContainingFile();
final VirtualFile virtualFile = containingFile.getVirtualFile();
final String clsFileName = virtualFile == null? containingFile.getName() : virtualFile.getPath();
final String clsFileNameWithoutExt = FileUtil.getNameWithoutExtension(clsFileName);
if (!clsFileNameWithoutExt.endsWith(fileName)) {
continue;
}
if (methodName == null) {
locations.add(new PsiLocation<PyClass>(project, cls));
}
else {
final PyFunction method = cls.findMethodByName(methodName, true);
if (method == null) {
continue;
}
locations.add(new PsiLocation<PyFunction>(project, method));
}
}
}
else if (methodName != null) {
for (PyFunction function : PyFunctionNameIndex.find(methodName, project)) {
ProgressManager.checkCanceled();
if (function.getContainingClass() == null) {
final PsiFile containingFile = function.getContainingFile();
final VirtualFile virtualFile = containingFile.getVirtualFile();
final String clsFileName = virtualFile == null? containingFile.getName() : virtualFile.getPath();
final String clsFileNameWithoutExt = FileUtil.getNameWithoutExtension(clsFileName);
if (!clsFileNameWithoutExt.endsWith(fileName)) {
continue;
}
locations.add(new PsiLocation<PyFunction>(project, function));
}
}
}
return locations;
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.testing.nosetest;
import com.intellij.execution.Location;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testIntegration.TestLocationProvider;
import com.jetbrains.python.testing.PythonUnitTestUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
public class PythonNoseTestUrlProvider implements TestLocationProvider {
@NonNls
private static final String PROTOCOL_ID = "python_nosetestid";
@NotNull
public List<Location> getLocation(@NotNull final String protocolId, @NotNull final String path,
final Project project) {
if (!PROTOCOL_ID.equals(protocolId)) {
return Collections.emptyList();
}
final List<String> list = StringUtil.split(path, ".");
if (list.isEmpty()) {
return Collections.emptyList();
}
final int listSize = list.size();
// parse path as [ns.]*fileName.className[.methodName]
if (listSize == 2) {
final List<Location> classes = PythonUnitTestUtil.findLocations(project, list.get(0), list.get(1), null);
if (classes.size() > 0)
return classes;
}
if (listSize > 2) {
final String className = list.get(listSize - 2);
final String methodName = list.get(listSize - 1);
String fileName = list.get(listSize - 3);
List<Location> locations = PythonUnitTestUtil.findLocations(project, fileName, className, methodName);
if (locations.size() > 0) {
return locations;
}
locations = PythonUnitTestUtil.findLocations(project, list.get(listSize - 2), list.get(listSize - 1), null);
if (locations.size() > 0) {
return locations;
}
final List<Location> functions = PythonUnitTestUtil.findLocations(project, list.get(listSize - 2), null, list.get(listSize - 1));
if (functions.size() > 0)
return functions;
}
return PythonUnitTestUtil.findLocations(project, project.getBasePath() + "/" + StringUtil.join(list, "/") + ".py", null, null);
}
}