From bcc4a00bbd01df671859fe870639fe1c5d9ae327 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 24 Apr 2014 16:11:42 +0200 Subject: [PATCH] junit category support (IDEA-88389) --- .../execution/junit/JUnitConfiguration.java | 34 +++++++- .../execution/junit/TestCategory.java | 70 ++++++++++++++++ .../intellij/execution/junit/TestObject.java | 17 +++- .../configuration/JUnitConfigurable.form | 19 +++-- .../configuration/JUnitConfigurable.java | 82 ++++++++++++++++++- .../JUnitConfigurationModel.java | 17 +++- .../com/intellij/junit3/TestRunnerUtil.java | 3 + .../src/com/intellij/junit4/IdeaSuite48.java | 46 +++++++++++ .../junit4/JUnit46ClassesRequestBuilder.java | 29 ++++++- .../intellij/junit4/JUnit4TestRunnerUtil.java | 5 +- 10 files changed, 296 insertions(+), 26 deletions(-) create mode 100644 plugins/junit/src/com/intellij/execution/junit/TestCategory.java create mode 100644 plugins/junit_rt/src/com/intellij/junit4/IdeaSuite48.java diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 422e567f8949..28cd670446e9 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -51,6 +51,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration myPattern = new LinkedHashSet(); + private Set myPattern = new LinkedHashSet(); //iws/ipr compatibility public String ENV_VARIABLES; private Map myEnvs = new LinkedHashMap(); - public boolean PASS_PARENT_ENVS = true; + public boolean PASS_PARENT_ENVS = true; public TestSearchScope.Wrapper TEST_SEARCH_SCOPE = new TestSearchScope.Wrapper(); public boolean equals(final Object object) { @@ -407,7 +423,8 @@ public class JUnitConfiguration extends ModuleBasedConfiguration testNames = new ArrayList(); for (final T element : elements) { final String name = nameFunction.fun(element); diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form index d49fabd40cae..1ac9026100d3 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form @@ -3,7 +3,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -133,7 +133,7 @@ - + @@ -182,10 +182,19 @@ - + + + + + + + + + + @@ -195,7 +204,7 @@ - + diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 07ba7c0d7f5e..d1ff8d5a9792 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -46,6 +46,7 @@ import com.intellij.openapi.ui.ex.MessagesEx; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.*; import com.intellij.ui.components.JBLabel; import com.intellij.util.IconUtil; @@ -72,7 +73,8 @@ public class JUnitConfigurable extends SettingsEditor implem new TIntArrayList(new int[]{1}), new TIntArrayList(new int[]{1, 2}), new TIntArrayList(new int[]{3}), - new TIntArrayList(new int[]{4}) + new TIntArrayList(new int[]{4}), + new TIntArrayList(new int[]{5}) ); private JComponent myPackagePanel; @@ -81,6 +83,7 @@ public class JUnitConfigurable extends SettingsEditor implem private LabeledComponent myPattern; private LabeledComponent myClass; private LabeledComponent myMethod; + private LabeledComponent myCategory; // Fields private JPanel myWholePanel; @@ -92,7 +95,7 @@ public class JUnitConfigurable extends SettingsEditor implem private TextFieldWithBrowseButton myPatternTextField; private final ConfigurationModuleSelector myModuleSelector; - private final LabeledComponent[] myTestLocations = new LabeledComponent[5]; + private final LabeledComponent[] myTestLocations = new LabeledComponent[6]; private final JUnitConfigurationModel myModel; private final BrowseModuleValueActionListener[] myBrowsers; @@ -135,7 +138,8 @@ public class JUnitConfigurable extends SettingsEditor implem } return null; } - } + }, + new CategoryBrowser(project) }; // Garbage support final DefaultComboBoxModel aModel = new DefaultComboBoxModel(); @@ -144,6 +148,7 @@ public class JUnitConfigurable extends SettingsEditor implem aModel.addElement(JUnitConfigurationModel.PATTERN); aModel.addElement(JUnitConfigurationModel.CLASS); aModel.addElement(JUnitConfigurationModel.METHOD); + aModel.addElement(JUnitConfigurationModel.CATEGORY); myTypeChooser.setModel(aModel); myTypeChooser.setRenderer(new ListCellRendererWrapper() { @Override @@ -164,6 +169,9 @@ public class JUnitConfigurable extends SettingsEditor implem case JUnitConfigurationModel.METHOD: setText("Method"); break; + case JUnitConfigurationModel.CATEGORY: + setText("Category"); + break; } } }); @@ -172,6 +180,7 @@ public class JUnitConfigurable extends SettingsEditor implem myTestLocations[JUnitConfigurationModel.CLASS] = myClass; myTestLocations[JUnitConfigurationModel.METHOD] = myMethod; myTestLocations[JUnitConfigurationModel.DIR] = myDir; + myTestLocations[JUnitConfigurationModel.CATEGORY] = myCategory; final JPanel panel = myPattern.getComponent(); panel.setLayout(new BorderLayout()); @@ -271,6 +280,7 @@ public class JUnitConfigurable extends SettingsEditor implem myScopesPanel.setVisible(true); myPattern.setVisible(false); myClass.setVisible(false); + myCategory.setVisible(false); myMethod.setVisible(false); myDir.setVisible(false); myForkCb.setEnabled(true); @@ -282,6 +292,7 @@ public class JUnitConfigurable extends SettingsEditor implem myDir.setVisible(true); myPattern.setVisible(false); myClass.setVisible(false); + myCategory.setVisible(false); myMethod.setVisible(false); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL)); @@ -293,6 +304,7 @@ public class JUnitConfigurable extends SettingsEditor implem myPattern.setVisible(false); myDir.setVisible(false); myClass.setVisible(true); + myCategory.setVisible(false); myMethod.setVisible(false); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE)); @@ -304,15 +316,29 @@ public class JUnitConfigurable extends SettingsEditor implem myPattern.setVisible(false); myDir.setVisible(false); myClass.setVisible(true); + myCategory.setVisible(false); myMethod.setVisible(true); myForkCb.setEnabled(false); myForkCb.setSelectedItem(NONE); - } else { + } else if (selectedType == JUnitConfigurationModel.CATEGORY) { + myPackagePanel.setVisible(false); + myScopesPanel.setVisible(true); + myDir.setVisible(false); + myPattern.setVisible(false); + myClass.setVisible(false); + myCategory.setVisible(true); + myMethod.setVisible(false); + myForkCb.setEnabled(true); + myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL)); + myForkCb.setSelectedItem(selectedItem); + } + else { myPackagePanel.setVisible(false); myScopesPanel.setVisible(true); myPattern.setVisible(true); myDir.setVisible(false); myClass.setVisible(false); + myCategory.setVisible(false); myMethod.setVisible(true); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL)); @@ -379,6 +405,17 @@ public class JUnitConfigurable extends SettingsEditor implem } })); + myCategory = new LabeledComponent(); + myCategory.setComponent(new EditorTextFieldWithBrowseButton(myProject, true, new JavaCodeFragment.VisibilityChecker() { + @Override + public Visibility isDeclarationVisible(PsiElement declaration, PsiElement place) { + if (declaration instanceof PsiClass) { + return Visibility.VISIBLE; + } + return Visibility.NOT_VISIBLE; + } + })); + myMethod = new LabeledComponent(); final EditorTextFieldWithBrowseButton textFieldWithBrowseButton = new EditorTextFieldWithBrowseButton(myProject, true, JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE, @@ -418,6 +455,7 @@ public class JUnitConfigurable extends SettingsEditor implem myMethod.setAnchor(anchor); myPattern.setAnchor(anchor); myPackage.setAnchor(anchor); + myCategory.setAnchor(anchor); } private static void addRadioButtonsListeners(final JRadioButton[] radioButtons, ChangeListener listener) { @@ -579,4 +617,40 @@ public class JUnitConfigurable extends SettingsEditor implem myCommonJavaParameters.applyTo(currentState); getModuleSelector().applyTo(currentState); } + + private class CategoryBrowser extends ClassBrowser { + public CategoryBrowser(Project project) { + super(project, "Category Interface"); + } + + protected PsiClass findClass(final String className) { + return myModuleSelector.findClass(className); + } + + protected ClassFilter.ClassFilterWithScope getFilter() throws NoFilterException { + final Module module = myModuleSelector.getModule(); + final GlobalSearchScope scope; + if (module == null) { + scope = GlobalSearchScope.allScope(myProject); + } + else { + scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module); + } + return new ClassFilter.ClassFilterWithScope() { + public GlobalSearchScope getScope() { + return scope; + } + + public boolean isAccepted(final PsiClass aClass) { + return true; + } + }; + } + + @Override + protected void onClassChoosen(PsiClass psiClass) { + ((LabeledComponent)getTestLocation(JUnitConfigurationModel.CATEGORY)).getComponent() + .setText(psiClass.getQualifiedName()); + } + } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java index 7e4745db4596..38a3ff9915e3 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java @@ -42,19 +42,23 @@ public class JUnitConfigurationModel { public static final int METHOD = 2; public static final int PATTERN = 3; public static final int DIR = 4; + public static final int CATEGORY = 5; private static final List ourTestObjects; static { - ourTestObjects = Arrays.asList(JUnitConfiguration.TEST_PACKAGE, JUnitConfiguration.TEST_CLASS, JUnitConfiguration.TEST_METHOD, + ourTestObjects = Arrays.asList(JUnitConfiguration.TEST_PACKAGE, + JUnitConfiguration.TEST_CLASS, + JUnitConfiguration.TEST_METHOD, JUnitConfiguration.TEST_PATTERN, - JUnitConfiguration.TEST_DIRECTORY); + JUnitConfiguration.TEST_DIRECTORY, + JUnitConfiguration.TEST_CATEGORY); } private JUnitConfigurable myListener; private int myType = -1; - private final Object[] myJUnitDocuments = new Object[5]; + private final Object[] myJUnitDocuments = new Object[6]; private final Project myProject; public JUnitConfigurationModel(final Project project) { @@ -99,7 +103,8 @@ public class JUnitConfigurationModel { data.TEST_OBJECT = testObject; if (testObject != JUnitConfiguration.TEST_PACKAGE && testObject != JUnitConfiguration.TEST_PATTERN && - testObject != JUnitConfiguration.TEST_DIRECTORY) { + testObject != JUnitConfiguration.TEST_DIRECTORY && + testObject != JUnitConfiguration.TEST_CATEGORY) { try { data.METHOD_NAME = getJUnitTextValue(METHOD); final PsiClass testClass = !myProject.isDefault() && !StringUtil.isEmptyOrSpaces(className) ? JUnitUtil.findPsiClass(className, module, myProject) : null; @@ -124,6 +129,9 @@ public class JUnitConfigurationModel { else if (testObject == JUnitConfiguration.TEST_DIRECTORY) { data.setDirName(getJUnitTextValue(DIR)); } + else if (testObject == JUnitConfiguration.TEST_CATEGORY) { + data.setCategoryName(getJUnitTextValue(CATEGORY)); + } else { final LinkedHashSet set = new LinkedHashSet(); final String[] patterns = getJUnitTextValue(PATTERN).split("\\|\\|"); @@ -168,6 +176,7 @@ public class JUnitConfigurationModel { setJUnitTextValue(METHOD, data.getMethodName()); setJUnitTextValue(PATTERN, data.getPatternPresentation()); setJUnitTextValue(DIR, data.getDirName()); + setJUnitTextValue(CATEGORY, data.getCategory()); } private void setJUnitTextValue(final int index, final String text) { diff --git a/plugins/junit_rt/src/com/intellij/junit3/TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit3/TestRunnerUtil.java index e6b94fb176b8..b2953134b77a 100644 --- a/plugins/junit_rt/src/com/intellij/junit3/TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit3/TestRunnerUtil.java @@ -52,6 +52,9 @@ public class TestRunnerUtil { Vector vector; try { suiteName = reader.readLine(); + + reader.readLine(); //category + vector = new Vector(); String line; while ((line = reader.readLine()) != null) { diff --git a/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite48.java b/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite48.java new file mode 100644 index 000000000000..1fcfbefd5b90 --- /dev/null +++ b/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite48.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2014 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.intellij.junit4; + +import org.junit.experimental.categories.Categories; +import org.junit.runner.manipulation.NoTestsRemainException; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; + +import java.util.List; + +public class IdeaSuite48 extends IdeaSuite { + public IdeaSuite48(List runners, String name, Class category) throws InitializationError { + super(runners, name); + filterByCategory(category); + } + + public IdeaSuite48(RunnerBuilder builder, Class[] classes, String name, Class category) throws InitializationError { + super(builder, classes, name); + filterByCategory(category); + } + + private void filterByCategory(Class category) throws InitializationError { + if (category != null) { + try { + final Categories.CategoryFilter categoryFilter = new Categories.CategoryFilter(category, null); + filter(categoryFilter); + } catch (NoTestsRemainException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit46ClassesRequestBuilder.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit46ClassesRequestBuilder.java index ef7961ff331a..ae090f3a04dc 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit46ClassesRequestBuilder.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit46ClassesRequestBuilder.java @@ -32,15 +32,36 @@ import java.util.*; public class JUnit46ClassesRequestBuilder { private JUnit46ClassesRequestBuilder() {} - public static Request getClassesRequest(final String suiteName, Class[] classes, Map classMethods) { + public static Request getClassesRequest(final String suiteName, Class[] classes, Map classMethods, Class category) { boolean canUseSuiteMethod = canUseSuiteMethod(classMethods); try { - final Runner suite; + if (category != null) { + try { + Class.forName("org.junit.experimental.categories.Categories"); + } + catch (ClassNotFoundException e) { + throw new RuntimeException("Categories are not available"); + } + } + + Runner suite; if (canUseSuiteMethod) { - suite = new IdeaSuite(collectWrappedRunners(classes), suiteName); + try { + Class.forName("org.junit.experimental.categories.Categories"); + suite = new IdeaSuite48(collectWrappedRunners(classes), suiteName, category); + } + catch (ClassNotFoundException e) { + suite = new IdeaSuite(collectWrappedRunners(classes), suiteName); + } } else { final AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder(canUseSuiteMethod); - suite = new IdeaSuite(builder, classes, suiteName); + try { + Class.forName("org.junit.experimental.categories.Categories"); + suite = new IdeaSuite48(builder, classes, suiteName, category); + } + catch (ClassNotFoundException e) { + suite = new IdeaSuite(builder, classes, suiteName); + } } return Request.runner(suite); } diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java index 4862015d9df5..d22ea44f2d8f 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java @@ -59,6 +59,9 @@ public class JUnit4TestRunnerUtil { try { final String packageName = reader.readLine(); if (packageName == null) return null; + + final String categoryName = reader.readLine(); + final Class category = categoryName != null && categoryName.length() > 0 ? loadTestClass(categoryName) : null; String line; while ((line = reader.readLine()) != null) { @@ -85,7 +88,7 @@ public class JUnit4TestRunnerUtil { Request allClasses; try { Class.forName("org.junit.runner.Computer"); - allClasses = JUnit46ClassesRequestBuilder.getClassesRequest(suiteName, classes, classMethods); + allClasses = JUnit46ClassesRequestBuilder.getClassesRequest(suiteName, classes, classMethods, category); } catch (ClassNotFoundException e) { allClasses = getClassRequestsUsing44API(suiteName, classes);