From 12c73e25cd57a3e28bb1ac9d609623ffc0fde409 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Tue, 7 Jun 2011 14:32:45 +0400 Subject: [PATCH] IDEA-70123 Test Assistant: Make it possible to work with test data for existing test classes that are not properly annotated Avoid tests without test data (e.g. pure unit tests) and take special caret to tests with too generic names (like 'test1', 'test2' etc). --- .../TestDataGuessByExistingFilesUtil.java | 95 ++++++++++++++++--- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java index 85c19f3c3aa0..0a058fefe388 100644 --- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java @@ -24,6 +24,7 @@ import com.intellij.util.text.Matcher; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.util.*; import java.util.concurrent.TimeUnit; @@ -39,6 +40,7 @@ public class TestDataGuessByExistingFilesUtil { private static final long CACHE_ENTRY_TTL_MS = TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES); private static final Map> CACHE = new ConcurrentHashMap>(); + private static final Set CLASSES_WITHOUT_TEST_DATA = new java.util.HashSet(); private TestDataGuessByExistingFilesUtil() { } @@ -137,6 +139,9 @@ public class TestDataGuessByExistingFilesUtil { } final String qualifiedName = psiClass.getQualifiedName(); + if (CLASSES_WITHOUT_TEST_DATA.contains(qualifiedName)) { + return null; + } final Pair cached = CACHE.get(qualifiedName); if (cached != null) { if (cached.first.isComplete()) { @@ -171,12 +176,66 @@ public class TestDataGuessByExistingFilesUtil { } testNames.add(name); } + ProjectFileIndex fileIndex = ProjectRootManager.getInstance(psiClass.getProject()).getFileIndex(); final TestDataDescriptor descriptor = buildDescriptor(gotoModel, fileIndex, testNames, psiClass); + if (isClassWithoutTestData(descriptor, testNames, psiClass)) { + CLASSES_WITHOUT_TEST_DATA.add(qualifiedName); + return null; + } CACHE.put(qualifiedName, new Pair(descriptor, System.currentTimeMillis() + CACHE_ENTRY_TTL_MS)); return descriptor; } + private static boolean isClassWithoutTestData(@NotNull TestDataDescriptor descriptor, @NotNull List testNames, + @NotNull PsiClass psiClass) { + if (testNames.size() <= 1) { + // There is a possible case that the test class is just created. + return false; + } + + if (!descriptor.isComplete()) { + return true; + } + + boolean tooGenericNames = true; + genericNamesLoop: + for (String testName : testNames) { + for (int i = 0; i < testName.length(); i++) { + if (!Character.isDigit(testName.charAt(i))) { + tooGenericNames = false; + break genericNamesLoop; + } + } + } + + final String simpleClassName = getSimpleClassName(psiClass); + if (tooGenericNames + && (simpleClassName == null || !descriptor.myDescriptors.get(0).dir.toLowerCase().contains(simpleClassName.toLowerCase()))) + { + return true; + } + + // We assume that test has test data if max(2; half of tests) tests already have test data. + int toMatch = Math.max(2, testNames.size() / 2); + for (String testName : testNames) { + if (toMatch <= 0) { + return false; + } + final List testDataFiles = descriptor.generate(testName); + for (String path : testDataFiles) { + if (new File(path).isFile()) { + // There is a possible case that particular test has only one test data file though the others have + // two (e.g. during testing caret position at virtual space). + toMatch--; + break; + } + } + } + + return toMatch > 0; + } + //@NotNull //private static Collection getMatchedFiles(@NotNull final Project project, @NotNull final String testName) { // final List result = new ArrayList(); @@ -308,6 +367,22 @@ public class TestDataGuessByExistingFilesUtil { return new TestDataDescriptor(descriptors); } + @Nullable + private static String getSimpleClassName(@NotNull PsiClass psiClass) { + String result = psiClass.getQualifiedName(); + if (result == null) { + return null; + } + if (result.endsWith("Test")) { + result = result.substring(0, result.length() - "Test".length()); + } + int i = result.lastIndexOf('.'); + if (i >= 0) { + result = result.substring(i + 1); + } + return result; + } + private static boolean moreRelevantPath(@NotNull TestLocationDescriptor candidate, @NotNull Set currentDescriptors, @NotNull PsiClass psiClass) @@ -333,18 +408,14 @@ public class TestDataGuessByExistingFilesUtil { } // By class name. - String pattern = className.toLowerCase(); - if (pattern.endsWith("test")) { - pattern = pattern.substring(0, pattern.length() - "Test".length()); - } - i = pattern.lastIndexOf('.'); - if (i >= 0) { - pattern = pattern.substring(i + 1); - } - candidateMatched = candidate.dir.toLowerCase().contains(pattern); - currentMatched = current.dir.toLowerCase().contains(pattern); - if (candidateMatched ^ currentMatched) { - return candidateMatched; + String simpleName = getSimpleClassName(psiClass); + if (simpleName != null) { + String pattern = simpleName.toLowerCase(); + candidateMatched = candidate.dir.toLowerCase().contains(pattern); + currentMatched = current.dir.toLowerCase().contains(pattern); + if (candidateMatched ^ currentMatched) { + return candidateMatched; + } } return false;