From 538db34fc0d3962eb9c9eb35efcc216d76e4399e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 16 Apr 2015 12:18:07 +0200 Subject: [PATCH] testng: extract strategy --- .../configuration/SearchingForTestsTask.java | 342 +----------------- .../configuration/TestNGConfiguration.java | 73 +--- .../TestNGConfigurationProducer.java | 3 +- .../TestNGConfigurationType.java | 4 +- .../testng/model/TestData.java | 49 +-- .../testng/model/TestNGTestClass.java | 95 +++++ .../testng/model/TestNGTestGroup.java | 63 ++++ .../testng/model/TestNGTestMethod.java | 110 ++++++ .../testng/model/TestNGTestObject.java | 247 +++++++++++++ .../testng/model/TestNGTestPackage.java | 103 ++++++ .../testng/model/TestNGTestPattern.java | 145 ++++++++ .../testng/model/TestNGTestSuite.java | 61 ++++ 12 files changed, 847 insertions(+), 448 deletions(-) create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestClass.java create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestGroup.java create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestMethod.java create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestObject.java create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPackage.java create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPattern.java create mode 100644 plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestSuite.java diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java index da4701d312ad..5dade70f8fce 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java @@ -20,40 +20,31 @@ */ package com.theoryinpractice.testng.configuration; -import com.intellij.codeInsight.AnnotationUtil; import com.intellij.execution.CantRunException; import com.intellij.execution.ExecutionException; import com.intellij.execution.testframework.SearchForTestsTask; -import com.intellij.execution.testframework.TestSearchScope; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.PackageScope; -import com.intellij.psi.search.searches.AnnotatedMembersSearch; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; import com.intellij.psi.util.ClassUtil; import com.theoryinpractice.testng.model.IDEARemoteTestRunnerClient; -import com.theoryinpractice.testng.model.TestClassFilter; import com.theoryinpractice.testng.model.TestData; +import com.theoryinpractice.testng.model.TestNGTestObject; import com.theoryinpractice.testng.model.TestType; import com.theoryinpractice.testng.util.TestNGUtil; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.testng.xml.*; import java.io.*; import java.net.ServerSocket; import java.util.*; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; public class SearchingForTestsTask extends SearchForTestsTask { private static final Logger LOG = Logger.getInstance("#" + SearchingForTestsTask.class.getName()); @@ -280,182 +271,9 @@ public class SearchingForTestsTask extends SearchForTestsTask { protected void fillTestObjects(final Map>> classes) throws CantRunException { - final TestData data = myConfig.getPersistantData(); - final PsiManager psiManager = PsiManager.getInstance(myProject); - if (data.TEST_OBJECT.equals(TestType.PACKAGE.getType())) { - final String packageName = data.getPackageName(); - PsiPackage psiPackage = ApplicationManager.getApplication().runReadAction( - new Computable() { - @Nullable - public PsiPackage compute() { - return JavaPsiFacade.getInstance(psiManager.getProject()).findPackage(packageName); - } - } - ); - if (psiPackage == null) { - throw CantRunException.packageNotFound(packageName); - } - else { - TestSearchScope scope = myConfig.getPersistantData().getScope(); - //TODO we should narrow this down by module really, if that's what's specified - TestClassFilter projectFilter = - new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true); - TestClassFilter filter = projectFilter.intersectionWith(PackageScope.packageScope(psiPackage, true)); - calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(filter, false)); - if (classes.size() == 0) { - throw new CantRunException("No tests found in the package \"" + packageName + '\"'); - } - } - } - else if (data.TEST_OBJECT.equals(TestType.CLASS.getType())) { - //it's a class - final PsiClass psiClass = ApplicationManager.getApplication().runReadAction( - new Computable() { - @Nullable - public PsiClass compute() { - return ClassUtil.findPsiClass(psiManager, data.getMainClassName().replace('/', '.'), null, true, getSearchScope()); - } - } - ); - if (psiClass == null) { - throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"'); - } - if (null == ApplicationManager.getApplication().runReadAction(new Computable() { - @Nullable - public String compute() { - return psiClass.getQualifiedName(); - } - })) { - throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"'); - } - calculateDependencies(null, classes, psiClass); - } - else if (data.TEST_OBJECT.equals(TestType.METHOD.getType())) { - //it's a method - final PsiClass psiClass = ApplicationManager.getApplication().runReadAction( - new Computable() { - @Nullable - public PsiClass compute() { - return ClassUtil.findPsiClass(psiManager, data.getMainClassName().replace('/', '.'), null, true, getSearchScope()); - } - } - ); - if (psiClass == null) { - throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"'); - } - if (null == ApplicationManager.getApplication().runReadAction( - new Computable() { - @Nullable - public String compute() { - return psiClass.getQualifiedName(); - } - } - )) { - throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"'); - } - collectTestMethods(classes, psiClass, data.getMethodName()); - } - else if (data.TEST_OBJECT.equals(TestType.GROUP.getType())) { - //for a group, we include all classes - PsiClass[] testClasses = TestNGUtil - .getAllTestClasses(new TestClassFilter(data.getScope().getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true), false); - if (testClasses != null) { - for (PsiClass c : testClasses) { - classes.put(c, new LinkedHashMap>()); - } - } - } - else if (data.TEST_OBJECT.equals(TestType.PATTERN.getType())) { - for (final String pattern : data.getPatterns()) { - final String className; - final String methodName; - if (pattern.contains(",")) { - methodName = StringUtil.getShortName(pattern, ','); - className = StringUtil.getPackageName(pattern, ','); - } else { - className = pattern; - methodName = null; - } - - final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { - @Nullable - @Override - public PsiClass compute() { - return ClassUtil.findPsiClass(psiManager, className.replace('/', '.'), null, true, getSearchScope()); - } - }); - if (psiClass != null) { - final Boolean hasTest = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public Boolean compute() { - return TestNGUtil.hasTest(psiClass); - } - }); - if (hasTest) { - if (StringUtil.isEmpty(methodName)) { - calculateDependencies(null, classes, psiClass); - } - else { - collectTestMethods(classes, psiClass, methodName); - } - } else { - throw new CantRunException("No tests found in class " + className); - } - } - } - if (classes.size() != data.getPatterns().size()) { - TestSearchScope scope = myConfig.getPersistantData().getScope(); - final List compilePatterns = new ArrayList(); - for (String p : data.getPatterns()) { - final Pattern compilePattern; - try { - compilePattern = Pattern.compile(p); - } - catch (PatternSyntaxException e) { - continue; - } - if (compilePattern != null) { - compilePatterns.add(compilePattern); - } - } - TestClassFilter projectFilter = - new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true){ - @Override - public boolean isAccepted(PsiClass psiClass) { - if (super.isAccepted(psiClass)) { - final String qualifiedName = psiClass.getQualifiedName(); - LOG.assertTrue(qualifiedName != null); - for (Pattern pattern : compilePatterns) { - if (pattern.matcher(qualifiedName).matches()) return true; - } - } - return false; - } - }; - calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(projectFilter, false)); - if (classes.size() == 0) { - throw new CantRunException("No tests found in for patterns \"" + StringUtil.join(data.getPatterns(), " || ") + '\"'); - } - } - } - } - - private void collectTestMethods(Map>> classes, final PsiClass psiClass, final String methodName) { - final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction( - new Computable() { - public PsiMethod[] compute() { - return psiClass.findMethodsByName(methodName, true); - } - } - ); - calculateDependencies(methods, classes, psiClass); - Map> psiMethods = classes.get(psiClass); - if (psiMethods == null) { - psiMethods = new LinkedHashMap>(); - classes.put(psiClass, psiMethods); - } - for (PsiMethod method : methods) { - psiMethods.put(method, Collections.emptyList()); + final TestNGTestObject testObject = TestNGTestObject.fromConfig(myConfig); + if (testObject != null) { + testObject.fillTestObjects(classes); } } @@ -492,152 +310,4 @@ public class SearchingForTestsTask extends SearchForTestsTask { return params; } - private void calculateDependencies(PsiMethod[] methods, - final Map>> results, - @Nullable final PsiClass... classes) { - calculateDependencies(methods, results, new LinkedHashSet(), classes); - } - - private void calculateDependencies(final PsiMethod[] methods, - final Map>> results, - final Set alreadyMarkedToBeChecked, - @Nullable final PsiClass... classes) { - if (classes != null && classes.length > 0) { - final Set groupDependencies = new LinkedHashSet(); - TestNGUtil.collectAnnotationValues(groupDependencies, "dependsOnGroups", methods, classes); - final Set membersToCheckNow = new LinkedHashSet(); - if (!groupDependencies.isEmpty()) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - final Project project = classes[0].getProject(); - final PsiClass testAnnotation = - JavaPsiFacade.getInstance(project).findClass(TestNGUtil.TEST_ANNOTATION_FQN, GlobalSearchScope.allScope(project)); - LOG.assertTrue(testAnnotation != null); - for (PsiMember psiMember : AnnotatedMembersSearch.search(testAnnotation, getSearchScope())) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotation(psiMember, TestNGUtil.TEST_ANNOTATION_FQN); - if (TestNGUtil.isAnnotatedWithParameter(annotation, "groups", groupDependencies)) { - if (appendMember(psiMember, alreadyMarkedToBeChecked, results)) { - membersToCheckNow.add(psiMember); - } - } - } - } - }); - } - - collectDependsOnMethods(results, alreadyMarkedToBeChecked, membersToCheckNow, methods, classes); - - if (methods == null) { - for (PsiClass c : classes) { - results.put(c, new LinkedHashMap>()); - } - } else { - for (PsiMember psiMember : membersToCheckNow) { - PsiClass psiClass; - PsiMethod[] meths = null; - if (psiMember instanceof PsiMethod) { - psiClass = psiMember.getContainingClass(); - meths = new PsiMethod[] {(PsiMethod)psiMember}; - } else { - psiClass = (PsiClass)psiMember; - } - calculateDependencies(meths, results, alreadyMarkedToBeChecked, psiClass); - } - } - } - } - - private static void collectDependsOnMethods(final Map>> results, - final Set alreadyMarkedToBeChecked, - final Set membersToCheckNow, - final PsiMethod[] methods, - final PsiClass... classes) { - final PsiClass[] psiClasses; - if (methods != null && methods.length > 0) { - final Set containingClasses = new LinkedHashSet(); - for (final PsiMethod method : methods) { - containingClasses.add(ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public PsiClass compute() { - return method.getContainingClass(); - } - })); - } - psiClasses = containingClasses.toArray(new PsiClass[containingClasses.size()]); - } else { - psiClasses = classes; - } - for (final PsiClass containingClass : psiClasses) { - final Set testMethodDependencies = new LinkedHashSet(); - TestNGUtil.collectAnnotationValues(testMethodDependencies, "dependsOnMethods", methods, containingClass); - if (!testMethodDependencies.isEmpty()) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - final Project project = containingClass.getProject(); - final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); - for (String dependency : testMethodDependencies) { - final String className = StringUtil.getPackageName(dependency); - final String methodName = StringUtil.getShortName(dependency); - if (StringUtil.isEmpty(className)) { - checkClassMethods(methodName, containingClass, alreadyMarkedToBeChecked, membersToCheckNow, results); - } - else { - final PsiClass aClass = psiFacade.findClass(className, containingClass.getResolveScope()); - if (aClass != null) { - checkClassMethods(methodName, aClass, alreadyMarkedToBeChecked, membersToCheckNow, results); - } - } - } - } - }); - } - } - } - - private static void checkClassMethods(String methodName, - PsiClass containingClass, - Set alreadyMarkedToBeChecked, - Set membersToCheckNow, - Map>> results) { - final PsiMethod[] psiMethods = containingClass.findMethodsByName(methodName, true); - for (PsiMethod method : psiMethods) { - if (AnnotationUtil.isAnnotated(method, TestNGUtil.TEST_ANNOTATION_FQN, false) && - appendMember(method, alreadyMarkedToBeChecked, results)) { - membersToCheckNow.add(method); - } - } - } - - private static boolean appendMember(final PsiMember psiMember, - final Set underConsideration, - final Map>> results) { - boolean result = false; - final PsiClass psiClass = psiMember instanceof PsiClass ? ((PsiClass)psiMember) : psiMember.getContainingClass(); - Map> psiMethods = results.get(psiClass); - if (psiMethods == null) { - psiMethods = new LinkedHashMap>(); - results.put(psiClass, psiMethods); - if (psiMember instanceof PsiClass) { - result = underConsideration.add(psiMember); - } - } - if (psiMember instanceof PsiMethod) { - final boolean add = psiMethods.put((PsiMethod)psiMember, Collections.emptyList()) != null; - if (add) { - return underConsideration.add(psiMember); - } - return false; - } - return result; - } - - @NotNull - private GlobalSearchScope getSearchScope() { - final TestData data = myConfig.getPersistantData(); - final Module module = myConfig.getConfigurationModule().getModule(); - return data.TEST_OBJECT.equals(TestType.PACKAGE.getType()) - ? myConfig.getPersistantData().getScope().getSourceScope(myConfig).getGlobalSearchScope() - : module != null ? GlobalSearchScope.moduleWithDependenciesScope(module) : GlobalSearchScope.projectScope(myConfig.getProject()); - } - } diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java index e051d95331e8..376e74bfcb1d 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java @@ -29,7 +29,6 @@ import com.intellij.execution.configuration.EnvironmentVariablesComponent; import com.intellij.execution.configurations.*; import com.intellij.execution.junit.RefactoringListeners; import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.execution.testframework.SourceScope; import com.intellij.execution.testframework.TestSearchScope; import com.intellij.execution.util.JavaParametersUtil; import com.intellij.execution.util.ProgramParametersUtil; @@ -47,12 +46,12 @@ import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.UndoRefactoringElementListener; import com.theoryinpractice.testng.model.TestData; +import com.theoryinpractice.testng.model.TestNGTestObject; import com.theoryinpractice.testng.model.TestType; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.testng.xml.Parser; import java.util.*; @@ -68,7 +67,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration 0) { - return "Tests in \"" + data.getPackageName() + '\"'; - } - else { - return "All Tests"; - } - } - if (TestType.METHOD.getType().equals(data.TEST_OBJECT)) { - return data.getMethodName() + "()"; - } - if (TestType.SUITE.getType().equals(data.TEST_OBJECT)) { - return data.getSuiteName(); - } - return data.getGroupName(); + final TestNGTestObject testObject = TestNGTestObject.fromConfig(this); + return testObject != null ? ProgramRunnerUtil.shortenName(testObject.getActionName(), 0) : null; } public void setVMParameters(String value) { @@ -299,45 +280,9 @@ public class TestNGConfiguration extends ModuleBasedConfiguration patterns = data.getPatterns(); - if (patterns.isEmpty()) { - throw new RuntimeConfigurationWarning("No pattern selected"); - } + final TestNGTestObject testObject = TestNGTestObject.fromConfig(this); + if (testObject != null) { + testObject.checkConfiguration(); } JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this); ProgramParametersUtil.checkWorkingDirectoryExist(this, getProject(), getConfigurationModule().getModule()); diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java index 5203f6c09819..f5dfadb86aef 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java @@ -33,6 +33,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiElement; import com.theoryinpractice.testng.model.TestData; +import com.theoryinpractice.testng.model.TestNGTestObject; import org.testng.IDEATestNGRemoteListener; public abstract class TestNGConfigurationProducer extends JavaRunConfigurationProducerBase implements Cloneable { @@ -58,7 +59,7 @@ public abstract class TestNGConfigurationProducer extends JavaRunConfigurationPr String paramSetName = contextLocation instanceof PsiMemberParameterizedLocation ? getInvocationNumber(((PsiMemberParameterizedLocation)contextLocation).getParamSetName()) : null; if (paramSetName != null && !Comparing.strEqual(paramSetName, testNGConfiguration.getProgramParameters())) return false; - TestData testobject = testNGConfiguration.getPersistantData(); + TestNGTestObject testobject = TestNGTestObject.fromConfig(testNGConfiguration); if (testobject != null) { if (testobject.isConfiguredByElement(element)) { final Module configurationModule = testNGConfiguration.getConfigurationModule().getModule(); diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationType.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationType.java index 3b7829dcb8b2..882e61c53b22 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationType.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationType.java @@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiElement; import com.theoryinpractice.testng.model.TestData; +import com.theoryinpractice.testng.model.TestNGTestObject; import icons.TestngIcons; import org.jetbrains.annotations.NotNull; @@ -72,7 +73,8 @@ public class TestNGConfigurationType implements ConfigurationType return false; else { final PsiElement element = location.getPsiElement(); - if (testobject.isConfiguredByElement(element)) { + final TestNGTestObject testNGTestObject = TestNGTestObject.fromConfig(config); + if (testNGTestObject != null && testNGTestObject.isConfiguredByElement(element)) { final Module configurationModule = config.getConfigurationModule().getModule(); if (Comparing.equal(location.getModule(), configurationModule)) return true; diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java index 2a75977483bb..48d925fbf93b 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java @@ -18,16 +18,15 @@ package com.theoryinpractice.testng.model; import com.intellij.execution.ExternalizablePath; import com.intellij.execution.JavaExecutionUtil; import com.intellij.execution.Location; -import com.intellij.execution.configurations.JavaRunConfigurationModule; import com.intellij.execution.junit.JUnitUtil; import com.intellij.execution.junit2.info.MethodLocation; import com.intellij.execution.testframework.TestSearchScope; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiPackage; import java.util.*; @@ -174,26 +173,6 @@ public class TestData implements Cloneable return data; } - public String getGeneratedName(JavaRunConfigurationModule runconfigurationmodule) { - if (TestType.PACKAGE.getType().equals(TEST_OBJECT)) if (getPackageName().length() == 0) return ""; - else return getPackageName(); - String name = JavaExecutionUtil.getPresentableClassName(getMainClassName()); - if (TestType.METHOD.getType().equals(TEST_OBJECT)) { - return name + '.' + getMethodName(); - } - else if (TestType.SUITE.getType().equals(TEST_OBJECT)) { - return getSuiteName(); - } - else { - if (TestType.PATTERN.getType().equals(TEST_OBJECT)) { - final int size = myPatterns.size(); - if (size == 0) return "Temp suite"; - return StringUtil.getShortName(myPatterns.iterator().next()) + (size > 1 ? " and " + (size - 1) + " more" : ""); - } - return name; - } - } - public String getMainClassName() { return MAIN_CLASS_NAME == null ? "" : MAIN_CLASS_NAME; } @@ -217,28 +196,6 @@ public class TestData implements Cloneable return JavaExecutionUtil.findModule(psiclass); } - public boolean isConfiguredByElement(PsiElement element) { - if (TEST_OBJECT.equals(TestType.PACKAGE.getType())) { - if (element instanceof PsiPackage) { - return Comparing.strEqual(PACKAGE_NAME, ((PsiPackage) element).getQualifiedName()); - } else if (element instanceof PsiDirectory) { - final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory)element)); - return psiPackage != null && Comparing.strEqual(PACKAGE_NAME, psiPackage.getQualifiedName()); - } - } - - element = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class, false); - if (element instanceof PsiMethod && TEST_OBJECT.equals(TestType.METHOD.getType())) { - final PsiClass aClass = ((PsiMethod) element).getContainingClass(); - return aClass != null && - Comparing.strEqual(MAIN_CLASS_NAME, JavaExecutionUtil.getRuntimeQualifiedName(aClass)) && - Comparing.strEqual(METHOD_NAME, ((PsiMethod) element).getName()); - } else if (element instanceof PsiClass && TEST_OBJECT.equals(TestType.CLASS.getType())) { - return Comparing.strEqual(MAIN_CLASS_NAME, JavaExecutionUtil.getRuntimeQualifiedName((PsiClass) element)); - } - return false; - } - public Map getEnvs() { return ENVS; } diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestClass.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestClass.java new file mode 100644 index 000000000000..16e1cd43afaf --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestClass.java @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.execution.CantRunException; +import com.intellij.execution.JavaExecutionUtil; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.execution.testframework.SourceScope; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.*; +import com.intellij.psi.util.ClassUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public class TestNGTestClass extends TestNGTestObject { + public TestNGTestClass(TestNGConfiguration config) { + super(config); + } + + @Override + public void fillTestObjects(Map>> classes) + throws CantRunException { + final TestData data = myConfig.getPersistantData(); + //it's a class + final PsiClass psiClass = ApplicationManager.getApplication().runReadAction( + new Computable() { + @Nullable + public PsiClass compute() { + return ClassUtil.findPsiClass(PsiManager.getInstance(myConfig.getProject()), data.getMainClassName().replace('/', '.'), null, true, getSearchScope()); + } + } + ); + if (psiClass == null) { + throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"'); + } + if (null == ApplicationManager.getApplication().runReadAction(new Computable() { + @Nullable + public String compute() { + return psiClass.getQualifiedName(); + } + })) { + throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"'); + } + calculateDependencies(null, classes, psiClass); + } + + @Override + public String getGeneratedName() { + return JavaExecutionUtil.getPresentableClassName(myConfig.getPersistantData().getMainClassName()); + } + + @Override + public String getActionName() { + return JavaExecutionUtil.getShortClassName(myConfig.getPersistantData().MAIN_CLASS_NAME); + } + + @Override + public void checkConfiguration() throws RuntimeConfigurationException { + final TestData data = myConfig.getPersistantData(); + final SourceScope scope = data.getScope().getSourceScope(myConfig); + if (scope == null) { + throw new RuntimeConfigurationException("Invalid scope specified"); + } + PsiClass psiClass = JavaPsiFacade.getInstance(myConfig.getProject()).findClass(data.getMainClassName(), scope.getGlobalSearchScope()); + if (psiClass == null) throw new RuntimeConfigurationException("Class '" + data.getMainClassName() + "' not found"); + } + + @Override + public boolean isConfiguredByElement(PsiElement element) { + element = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class, false); + if (element instanceof PsiClass) { + return Comparing.strEqual(myConfig.getPersistantData().getMethodName(), JavaExecutionUtil.getRuntimeQualifiedName((PsiClass) element)); + } + return false; + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestGroup.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestGroup.java new file mode 100644 index 000000000000..ef24a830ec65 --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestGroup.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.execution.CantRunException; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import com.theoryinpractice.testng.util.TestNGUtil; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class TestNGTestGroup extends TestNGTestObject { + public TestNGTestGroup(TestNGConfiguration config) { + super(config); + } + + @Override + public void fillTestObjects(Map>> classes) + throws CantRunException { + final TestData data = myConfig.getPersistantData(); + //for a group, we include all classes + final TestClassFilter classFilter = + new TestClassFilter(data.getScope().getSourceScope(myConfig).getGlobalSearchScope(), myConfig.getProject(), true, true); + PsiClass[] testClasses = TestNGUtil.getAllTestClasses(classFilter, false); + if (testClasses != null) { + for (PsiClass c : testClasses) { + classes.put(c, new LinkedHashMap>()); + } + } + } + + @Override + public String getGeneratedName() { + return myConfig.getPersistantData().getGroupName(); + } + + @Override + public String getActionName() { + return myConfig.getPersistantData().getGroupName(); + } + + @Override + public void checkConfiguration() throws RuntimeConfigurationException { + //check group exist? + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestMethod.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestMethod.java new file mode 100644 index 000000000000..16e08f4de0de --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestMethod.java @@ -0,0 +1,110 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.execution.CantRunException; +import com.intellij.execution.JavaExecutionUtil; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.execution.testframework.SourceScope; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.*; +import com.intellij.psi.util.ClassUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public class TestNGTestMethod extends TestNGTestObject { + public TestNGTestMethod(TestNGConfiguration config) { + super(config); + } + + @Override + public void fillTestObjects(Map>> classes) + throws CantRunException { + final TestData data = myConfig.getPersistantData(); + final PsiClass psiClass = ApplicationManager.getApplication().runReadAction( + new Computable() { + @Nullable + public PsiClass compute() { + return ClassUtil.findPsiClass(PsiManager.getInstance(myConfig.getProject()), data.getMainClassName().replace('/', '.'), null, true, getSearchScope()); + } + } + ); + if (psiClass == null) { + throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"'); + } + if (null == ApplicationManager.getApplication().runReadAction( + new Computable() { + @Nullable + public String compute() { + return psiClass.getQualifiedName(); + } + } + )) { + throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"'); + } + collectTestMethods(classes, psiClass, data.getMethodName()); + } + + @Override + public String getGeneratedName() { + final TestData data = myConfig.getPersistantData(); + return JavaExecutionUtil.getPresentableClassName(data.getMainClassName()) + '.' + data.getMethodName(); + } + + @Override + public String getActionName() { + return myConfig.getPersistantData().getMethodName() + "()"; + } + + @Override + public void checkConfiguration() throws RuntimeConfigurationException { + final TestData data = myConfig.getPersistantData(); + final SourceScope scope = data.getScope().getSourceScope(myConfig); + if (scope == null) { + throw new RuntimeConfigurationException("Invalid scope specified"); + } + PsiClass psiClass = JavaPsiFacade.getInstance(myConfig.getProject()).findClass(data.getMainClassName(), scope.getGlobalSearchScope()); + if (psiClass == null) throw new RuntimeConfigurationException("Class '" + data.getMainClassName() + "' not found"); + PsiMethod[] methods = psiClass.findMethodsByName(data.getMethodName(), true); + if (methods.length == 0) { + throw new RuntimeConfigurationException("Method '" + data.getMethodName() + "' not found"); + } + for (PsiMethod method : methods) { + if (!method.hasModifierProperty(PsiModifier.PUBLIC)) { + throw new RuntimeConfigurationException("Non public method '" + data.getMethodName() + "'specified"); + } + } + } + + @Override + public boolean isConfiguredByElement(PsiElement element) { + element = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class, false); + if (element instanceof PsiMethod) { + final PsiClass aClass = ((PsiMethod) element).getContainingClass(); + final TestData data = myConfig.getPersistantData(); + return aClass != null && + Comparing.strEqual(data.MAIN_CLASS_NAME, JavaExecutionUtil.getRuntimeQualifiedName(aClass)) && + Comparing.strEqual(data.METHOD_NAME, ((PsiMethod) element).getName()); + } + return false; + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestObject.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestObject.java new file mode 100644 index 000000000000..2f839e5aaefb --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestObject.java @@ -0,0 +1,247 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.execution.CantRunException; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.AnnotatedMembersSearch; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import com.theoryinpractice.testng.util.TestNGUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public abstract class TestNGTestObject { + private static final Logger LOG = Logger.getInstance("#" + TestNGTestObject.class.getName()); + protected final TestNGConfiguration myConfig; + + public TestNGTestObject(TestNGConfiguration config) { + myConfig = config; + } + + public static TestNGTestObject fromConfig(TestNGConfiguration config) { + final TestData data = config.getPersistantData(); + if (data.TEST_OBJECT.equals(TestType.PACKAGE.getType())) { + return new TestNGTestPackage(config); + } + if (data.TEST_OBJECT.equals(TestType.CLASS.getType())) { + return new TestNGTestClass(config); + } + if (data.TEST_OBJECT.equals(TestType.METHOD.getType())) { + return new TestNGTestMethod(config); + } + + if (data.TEST_OBJECT.equals(TestType.GROUP.getType())) { + return new TestNGTestGroup(config); + } + + if (data.TEST_OBJECT.equals(TestType.PATTERN.getType())) { + return new TestNGTestPattern(config); + } + + if (data.TEST_OBJECT.equals(TestType.SUITE.getType())){ + return new TestNGTestSuite(config); + } + assert false : data.TEST_OBJECT; + return null; + } + + public abstract void fillTestObjects(final Map>> classes) throws CantRunException; + public abstract String getGeneratedName(); + public abstract String getActionName(); + public abstract void checkConfiguration() throws RuntimeConfigurationException; + + public boolean isConfiguredByElement(PsiElement element) { + return false; + } + + protected void calculateDependencies(PsiMethod[] methods, + final Map>> results, + @Nullable final PsiClass... classes) { + calculateDependencies(methods, results, new LinkedHashSet(), classes); + } + + private void calculateDependencies(final PsiMethod[] methods, + final Map>> results, + final Set alreadyMarkedToBeChecked, + @Nullable final PsiClass... classes) { + if (classes != null && classes.length > 0) { + final Set groupDependencies = new LinkedHashSet(); + TestNGUtil.collectAnnotationValues(groupDependencies, "dependsOnGroups", methods, classes); + final Set membersToCheckNow = new LinkedHashSet(); + if (!groupDependencies.isEmpty()) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + final Project project = classes[0].getProject(); + final PsiClass testAnnotation = + JavaPsiFacade.getInstance(project).findClass(TestNGUtil.TEST_ANNOTATION_FQN, GlobalSearchScope.allScope(project)); + LOG.assertTrue(testAnnotation != null); + for (PsiMember psiMember : AnnotatedMembersSearch.search(testAnnotation, getSearchScope())) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(psiMember, TestNGUtil.TEST_ANNOTATION_FQN); + if (TestNGUtil.isAnnotatedWithParameter(annotation, "groups", groupDependencies)) { + if (appendMember(psiMember, alreadyMarkedToBeChecked, results)) { + membersToCheckNow.add(psiMember); + } + } + } + } + }); + } + + collectDependsOnMethods(results, alreadyMarkedToBeChecked, membersToCheckNow, methods, classes); + + if (methods == null) { + for (PsiClass c : classes) { + results.put(c, new LinkedHashMap>()); + } + } else { + for (PsiMember psiMember : membersToCheckNow) { + PsiClass psiClass; + PsiMethod[] meths = null; + if (psiMember instanceof PsiMethod) { + psiClass = psiMember.getContainingClass(); + meths = new PsiMethod[] {(PsiMethod)psiMember}; + } else { + psiClass = (PsiClass)psiMember; + } + calculateDependencies(meths, results, alreadyMarkedToBeChecked, psiClass); + } + } + } + } + + private static void collectDependsOnMethods(final Map>> results, + final Set alreadyMarkedToBeChecked, + final Set membersToCheckNow, + final PsiMethod[] methods, + final PsiClass... classes) { + final PsiClass[] psiClasses; + if (methods != null && methods.length > 0) { + final Set containingClasses = new LinkedHashSet(); + for (final PsiMethod method : methods) { + containingClasses.add(ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiClass compute() { + return method.getContainingClass(); + } + })); + } + psiClasses = containingClasses.toArray(new PsiClass[containingClasses.size()]); + } else { + psiClasses = classes; + } + for (final PsiClass containingClass : psiClasses) { + final Set testMethodDependencies = new LinkedHashSet(); + TestNGUtil.collectAnnotationValues(testMethodDependencies, "dependsOnMethods", methods, containingClass); + if (!testMethodDependencies.isEmpty()) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + final Project project = containingClass.getProject(); + final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); + for (String dependency : testMethodDependencies) { + final String className = StringUtil.getPackageName(dependency); + final String methodName = StringUtil.getShortName(dependency); + if (StringUtil.isEmpty(className)) { + checkClassMethods(methodName, containingClass, alreadyMarkedToBeChecked, membersToCheckNow, results); + } + else { + final PsiClass aClass = psiFacade.findClass(className, containingClass.getResolveScope()); + if (aClass != null) { + checkClassMethods(methodName, aClass, alreadyMarkedToBeChecked, membersToCheckNow, results); + } + } + } + } + }); + } + } + } + + private static void checkClassMethods(String methodName, + PsiClass containingClass, + Set alreadyMarkedToBeChecked, + Set membersToCheckNow, + Map>> results) { + final PsiMethod[] psiMethods = containingClass.findMethodsByName(methodName, true); + for (PsiMethod method : psiMethods) { + if (AnnotationUtil.isAnnotated(method, TestNGUtil.TEST_ANNOTATION_FQN, false) && + appendMember(method, alreadyMarkedToBeChecked, results)) { + membersToCheckNow.add(method); + } + } + } + + private static boolean appendMember(final PsiMember psiMember, + final Set underConsideration, + final Map>> results) { + boolean result = false; + final PsiClass psiClass = psiMember instanceof PsiClass ? ((PsiClass)psiMember) : psiMember.getContainingClass(); + Map> psiMethods = results.get(psiClass); + if (psiMethods == null) { + psiMethods = new LinkedHashMap>(); + results.put(psiClass, psiMethods); + if (psiMember instanceof PsiClass) { + result = underConsideration.add(psiMember); + } + } + if (psiMember instanceof PsiMethod) { + final boolean add = psiMethods.put((PsiMethod)psiMember, Collections.emptyList()) != null; + if (add) { + return underConsideration.add(psiMember); + } + return false; + } + return result; + } + + @NotNull + protected GlobalSearchScope getSearchScope() { + final TestData data = myConfig.getPersistantData(); + final Module module = myConfig.getConfigurationModule().getModule(); + return data.TEST_OBJECT.equals(TestType.PACKAGE.getType()) + ? myConfig.getPersistantData().getScope().getSourceScope(myConfig).getGlobalSearchScope() + : module != null ? GlobalSearchScope.moduleWithDependenciesScope(module) : GlobalSearchScope.projectScope(myConfig.getProject()); + } + + protected void collectTestMethods(Map>> classes, final PsiClass psiClass, final String methodName) { + final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction( + new Computable() { + public PsiMethod[] compute() { + return psiClass.findMethodsByName(methodName, true); + } + } + ); + calculateDependencies(methods, classes, psiClass); + Map> psiMethods = classes.get(psiClass); + if (psiMethods == null) { + psiMethods = new LinkedHashMap>(); + classes.put(psiClass, psiMethods); + } + for (PsiMethod method : methods) { + psiMethods.put(method, Collections.emptyList()); + } + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPackage.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPackage.java new file mode 100644 index 000000000000..0a6315b41706 --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPackage.java @@ -0,0 +1,103 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.execution.CantRunException; +import com.intellij.execution.JavaExecutionUtil; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.execution.testframework.TestSearchScope; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.*; +import com.intellij.psi.search.PackageScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import com.theoryinpractice.testng.util.TestNGUtil; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public class TestNGTestPackage extends TestNGTestObject { + public TestNGTestPackage(TestNGConfiguration configuration) { + super(configuration); + } + + @Override + public void fillTestObjects(Map>> classes) throws CantRunException { + final String packageName = myConfig.getPersistantData().getPackageName(); + PsiPackage psiPackage = ApplicationManager.getApplication().runReadAction( + new Computable() { + @Nullable + public PsiPackage compute() { + return JavaPsiFacade.getInstance(myConfig.getProject()).findPackage(packageName); + } + } + ); + if (psiPackage == null) { + throw CantRunException.packageNotFound(packageName); + } + else { + TestSearchScope scope = myConfig.getPersistantData().getScope(); + //TODO we should narrow this down by module really, if that's what's specified + TestClassFilter projectFilter = + new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myConfig.getProject(), true, true); + TestClassFilter filter = projectFilter.intersectionWith(PackageScope.packageScope(psiPackage, true)); + calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(filter, false)); + if (classes.size() == 0) { + throw new CantRunException("No tests found in the package \"" + packageName + '\"'); + } + } + } + + @Override + public String getGeneratedName() { + final String packageName = myConfig.getPersistantData().getPackageName(); + return packageName.length() == 0 ? "" : packageName; + } + + @Override + public String getActionName() { + String s = myConfig.getName(); + if (!myConfig.isGeneratedName()) return '\"' + s + '\"'; + if (myConfig.getPersistantData().getPackageName().trim().length() > 0) { + return "Tests in \"" + myConfig.getPersistantData().getPackageName() + '\"'; + } + else { + return "All Tests"; + } + } + + @Override + public void checkConfiguration() throws RuntimeConfigurationException { + final TestData data = myConfig.getPersistantData(); + PsiPackage psiPackage = JavaPsiFacade.getInstance(myConfig.getProject()).findPackage(data.getPackageName()); + if (psiPackage == null) throw new RuntimeConfigurationException("Package '" + data.getPackageName() + "' not found"); + } + + @Override + public boolean isConfiguredByElement(PsiElement element) { + final String packageName = myConfig.getPersistantData().getPackageName(); + if (element instanceof PsiPackage) { + return Comparing.strEqual(packageName, ((PsiPackage)element).getQualifiedName()); + } else if (element instanceof PsiDirectory) { + final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory)element)); + return psiPackage != null && Comparing.strEqual(packageName, psiPackage.getQualifiedName()); + } + return false; + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPattern.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPattern.java new file mode 100644 index 000000000000..78e56e27de73 --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestPattern.java @@ -0,0 +1,145 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.execution.CantRunException; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.execution.configurations.RuntimeConfigurationWarning; +import com.intellij.execution.testframework.TestSearchScope; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.ClassUtil; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import com.theoryinpractice.testng.util.TestNGUtil; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +public class TestNGTestPattern extends TestNGTestObject { + private static final Logger LOG = Logger.getInstance("#" + TestNGTestPattern.class.getName()); + + public TestNGTestPattern(TestNGConfiguration config) { + super(config); + } + + @Override + public void fillTestObjects(Map>> classes) + throws CantRunException { + final TestData data = myConfig.getPersistantData(); + for (final String pattern : data.getPatterns()) { + final String className; + final String methodName; + if (pattern.contains(",")) { + methodName = StringUtil.getShortName(pattern, ','); + className = StringUtil.getPackageName(pattern, ','); + } else { + className = pattern; + methodName = null; + } + + final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { + @Nullable + @Override + public PsiClass compute() { + return ClassUtil.findPsiClass(PsiManager.getInstance(myConfig.getProject()), className.replace('/', '.'), null, true, getSearchScope()); + } + }); + if (psiClass != null) { + final Boolean hasTest = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + return TestNGUtil.hasTest(psiClass); + } + }); + if (hasTest) { + if (StringUtil.isEmpty(methodName)) { + calculateDependencies(null, classes, psiClass); + } + else { + collectTestMethods(classes, psiClass, methodName); + } + } else { + throw new CantRunException("No tests found in class " + className); + } + } + } + if (classes.size() != data.getPatterns().size()) { + TestSearchScope scope = myConfig.getPersistantData().getScope(); + final List compilePatterns = new ArrayList(); + for (String p : data.getPatterns()) { + final Pattern compilePattern; + try { + compilePattern = Pattern.compile(p); + } + catch (PatternSyntaxException e) { + continue; + } + if (compilePattern != null) { + compilePatterns.add(compilePattern); + } + } + TestClassFilter projectFilter = + new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myConfig.getProject(), true, true){ + @Override + public boolean isAccepted(PsiClass psiClass) { + if (super.isAccepted(psiClass)) { + final String qualifiedName = psiClass.getQualifiedName(); + LOG.assertTrue(qualifiedName != null); + for (Pattern pattern : compilePatterns) { + if (pattern.matcher(qualifiedName).matches()) return true; + } + } + return false; + } + }; + calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(projectFilter, false)); + if (classes.size() == 0) { + throw new CantRunException("No tests found in for patterns \"" + StringUtil.join(data.getPatterns(), " || ") + '\"'); + } + } + } + + @Override + public String getGeneratedName() { + final Set patterns = myConfig.getPersistantData().getPatterns(); + final int size = patterns.size(); + if (size == 0) return "Temp suite"; + return StringUtil.getShortName(patterns.iterator().next()) + (size > 1 ? " and " + (size - 1) + " more" : ""); + } + + @Override + public String getActionName() { + return getGeneratedName(); + } + + @Override + public void checkConfiguration() throws RuntimeConfigurationException { + final Set patterns = myConfig.getPersistantData().getPatterns(); + if (patterns.isEmpty()) { + throw new RuntimeConfigurationWarning("No pattern selected"); + } + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestSuite.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestSuite.java new file mode 100644 index 000000000000..875891671ccb --- /dev/null +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGTestSuite.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2015 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.theoryinpractice.testng.model; + +import com.intellij.execution.CantRunException; +import com.intellij.execution.configurations.RuntimeConfigurationException; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import org.testng.xml.Parser; + +import java.util.List; +import java.util.Map; + +public class TestNGTestSuite extends TestNGTestObject { + private static final Object PARSE_LOCK = new Object(); + public TestNGTestSuite(TestNGConfiguration config) { + super(config); + } + + @Override + public void fillTestObjects(Map>> classes) throws CantRunException {} + + @Override + public String getGeneratedName() { + return myConfig.getPersistantData().getSuiteName(); + } + + @Override + public String getActionName() { + return myConfig.getPersistantData().getSuiteName(); + } + + @Override + public void checkConfiguration() throws RuntimeConfigurationException { + final TestData data = myConfig.getPersistantData(); + try { + final Parser parser = new Parser(data.getSuiteName()); + parser.setLoadClasses(false); + synchronized (PARSE_LOCK) { + parser.parse();//try to parse suite.xml + } + } + catch (Exception e) { + throw new RuntimeConfigurationException("Unable to parse '" + data.getSuiteName() + "' specified"); + } + } +}