diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java index 5da776039800..da55d9203f15 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java +++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java @@ -81,6 +81,7 @@ public class JUnitUtil { @NonNls public static final String PARAMETERIZED_CLASS_NAME = "org.junit.runners.Parameterized"; @NonNls public static final String SUITE_CLASS_NAME = "org.junit.runners.Suite"; + public static final String JUNIT5_NESTED = "org.junit.jupiter.api.Nested"; public static boolean isSuiteMethod(@NotNull PsiMethod psiMethod) { if (!psiMethod.hasModifierProperty(PsiModifier.PUBLIC)) return false; @@ -200,6 +201,10 @@ public class JUnitUtil { final PsiModifierList modifierList = psiClass.getModifierList(); if (modifierList == null) return false; + if (psiClass.getContainingClass() != null && AnnotationUtil.isAnnotated(psiClass, JUNIT5_NESTED, false)) { + return true; + } + if (!PsiClassUtil.isRunnableClass(psiClass, false, checkAbstract)) return false; for (final PsiMethod method : psiClass.getAllMethods()) { @@ -207,6 +212,10 @@ public class JUnitUtil { if (AnnotationUtil.isAnnotated(method, TEST5_ANNOTATIONS)) return true; } + for (PsiClass aClass : psiClass.getInnerClasses()) { + if (AnnotationUtil.isAnnotated(aClass, JUNIT5_NESTED, false)) return true; + } + return false; } diff --git a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java index e235ffb606f6..37e8b3324ee0 100644 --- a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java +++ b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java @@ -96,7 +96,17 @@ public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction { private static PsiClass findTargetClass(@NotNull Editor editor, @NotNull PsiFile file) { int offset = editor.getCaretModel().getOffset(); PsiElement element = file.findElementAt(offset); - return PsiTreeUtil.getParentOfType(element, PsiClass.class, false) == null ? null : TestIntegrationUtils.findOuterClass(element); + PsiClass containingClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false); + if (containingClass == null) { + return null; + } + final List frameworks = TestIntegrationUtils.findSuitableFrameworks(containingClass); + for (TestFramework framework : frameworks) { + if (framework instanceof JavaTestFramework && ((JavaTestFramework)framework).acceptNestedClasses()) { + return containingClass; + } + } + return TestIntegrationUtils.findOuterClass(element); } @Override @@ -155,10 +165,10 @@ public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction { .createPopup().showInBestPositionFor(editor); } - private static class MyHandler implements CodeInsightActionHandler { + public static class MyHandler implements CodeInsightActionHandler { private final TestIntegrationUtils.MethodKind myMethodKind; - private MyHandler(TestIntegrationUtils.MethodKind methodKind) { + public MyHandler(TestIntegrationUtils.MethodKind methodKind) { myMethodKind = methodKind; } @@ -206,7 +216,7 @@ public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction { WriteCommandAction.runWriteCommandAction(file.getProject(), () -> { try { PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); - PsiMethod method = generateDummyMethod(editor, file); + PsiMethod method = generateDummyMethod(file, editor, targetClass); if (method == null) return; TestIntegrationUtils.runTestMethodTemplate(myMethodKind, framework, editor, targetClass, method, "name", false, null); @@ -219,21 +229,24 @@ public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction { } @Nullable - private static PsiMethod generateDummyMethod(Editor editor, PsiFile file) throws IncorrectOperationException { + private static PsiMethod generateDummyMethod(PsiFile file, Editor editor, PsiClass targetClass) throws IncorrectOperationException { final PsiMethod method = TestIntegrationUtils.createDummyMethod(file); final PsiGenerationInfo info = OverrideImplementUtil.createGenerationInfo(method); - int offset = findOffsetToInsertMethodTo(editor, file); + int offset = findOffsetToInsertMethodTo(editor, file, targetClass); GenerateMembersUtil.insertMembersAtOffset(file, offset, Collections.singletonList(info)); final PsiMethod member = info.getPsiMember(); return member != null ? CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(member) : null; } - private static int findOffsetToInsertMethodTo(Editor editor, PsiFile file) { + private static int findOffsetToInsertMethodTo(Editor editor, PsiFile file, PsiClass targetClass) { int result = editor.getCaretModel().getOffset(); PsiClass classAtCursor = PsiTreeUtil.getParentOfType(file.findElementAt(result), PsiClass.class, false); + if (classAtCursor == targetClass) { + return result; + } while (classAtCursor != null && !(classAtCursor.getParent() instanceof PsiFile)) { result = classAtCursor.getTextRange().getEndOffset(); diff --git a/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java b/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java index bf46ae119e90..3d1b76e88f7e 100644 --- a/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java +++ b/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java @@ -162,4 +162,7 @@ public abstract class JavaTestFramework implements TestFramework { } + public boolean acceptNestedClasses() { + return false; + } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnit5Framework.java b/plugins/junit/src/com/intellij/execution/junit/JUnit5Framework.java index 8d04dd4039cd..49b3d3892b74 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnit5Framework.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnit5Framework.java @@ -134,6 +134,11 @@ public class JUnit5Framework extends JavaTestFramework { return JUnitUtil.isTestMethod(MethodLocation.elementInClass(method, myClass)); } + @Override + public boolean acceptNestedClasses() { + return true; + } + public FileTemplateDescriptor getSetUpMethodFileTemplateDescriptor() { return new FileTemplateDescriptor("JUnit5 SetUp Method.java"); } diff --git a/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5AcceptanceTest.java b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5AcceptanceTest.java index 4bdcbc88dbc4..129d81ebceed 100644 --- a/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5AcceptanceTest.java +++ b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5AcceptanceTest.java @@ -21,15 +21,8 @@ import com.intellij.execution.junit.JUnitConfiguration; import com.intellij.execution.junit.JUnitUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; -import com.intellij.testFramework.EdtTestUtil; -import com.intellij.testFramework.TestRunnerUtil; -import com.intellij.testFramework.fixtures.*; -import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; import com.intellij.testIntegration.TestFramework; -import com.intellij.util.ThrowableRunnable; import one.util.streamex.StreamEx; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -39,23 +32,7 @@ import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; -class JUnit5AcceptanceTest { - - private JavaCodeInsightTestFixture myFixture; - - @BeforeEach - void setUp() throws Exception { - IdeaTestFixtureFactory factory = IdeaTestFixtureFactory.getFixtureFactory(); - TestFixtureBuilder fixtureBuilder = factory.createLightFixtureBuilder(new DefaultLightProjectDescriptor()); - final IdeaProjectTestFixture fixture = fixtureBuilder.getFixture(); - myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixture, new LightTempDirTestFixtureImpl(true)); - myFixture.setUp(); - } - - @AfterEach - void tearDown() throws Exception { - myFixture.tearDown(); - } +class JUnit5AcceptanceTest extends JUnit5CodeInsightTest { @Test void testFactoryMethods() { @@ -127,9 +104,4 @@ class JUnit5AcceptanceTest { }); } - - private static void doTest(ThrowableRunnable run) { - TestRunnerUtil.replaceIdeEventQueueSafely(); - EdtTestUtil.runInEdtAndWait(run); - } } diff --git a/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5CodeInsightTest.java b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5CodeInsightTest.java new file mode 100644 index 000000000000..2123f9ea1990 --- /dev/null +++ b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5CodeInsightTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2016 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.junit5; + +import com.intellij.testFramework.EdtTestUtil; +import com.intellij.testFramework.TestRunnerUtil; +import com.intellij.testFramework.fixtures.*; +import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; +import com.intellij.util.ThrowableRunnable; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +class JUnit5CodeInsightTest { + protected JavaCodeInsightTestFixture myFixture; + + @BeforeEach + void setUp() throws Exception { + IdeaTestFixtureFactory factory = IdeaTestFixtureFactory.getFixtureFactory(); + TestFixtureBuilder fixtureBuilder = factory.createLightFixtureBuilder(new DefaultLightProjectDescriptor()); + final IdeaProjectTestFixture fixture = fixtureBuilder.getFixture(); + myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixture, new LightTempDirTestFixtureImpl(true)); + myFixture.setUp(); + } + + @AfterEach + void tearDown() throws Exception { + myFixture.tearDown(); + } + + protected static void doTest(ThrowableRunnable run) { + TestRunnerUtil.replaceIdeEventQueueSafely(); + EdtTestUtil.runInEdtAndWait(run); + } +} diff --git a/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5GenerationTest.java b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5GenerationTest.java new file mode 100644 index 000000000000..37e519adff1d --- /dev/null +++ b/plugins/junit5_rt_tests/test/com/intellij/junit5/JUnit5GenerationTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2016 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.junit5; + +import com.intellij.testIntegration.BaseGenerateTestSupportMethodAction; +import com.intellij.testIntegration.TestIntegrationUtils; +import org.junit.jupiter.api.Test; + +class JUnit5GenerationTest extends JUnit5CodeInsightTest { + @Test + void testMethodInTopLevelClass() { + doTest("import org.junit.jupiter.api.Test; class MyTest { @Test void m2(){}}", + "import org.junit.jupiter.api.Test; class MyTest {\n" + + " @Test\n" + + " void name() {\n" + + " \n" + + "\n" + + " }\n" + + "\n" + + " @Test void m2(){}}"); + } + + @Test + void testMethodInNestedClass() { + doTest("import org.junit.jupiter.api.Nested; class MyTest { @Nested class NTest { }}", + "import org.junit.jupiter.api.Nested;\n" + + "import org.junit.jupiter.api.Test;\n" + + "\n" + + "class MyTest { @Nested class NTest {\n" + + " @Test\n" + + " void name() {\n" + + " \n" + + "\n" + + " }\n" + + "}}"); + } + + private void doTest(String text, String expected) { + doTest(() -> { + myFixture.addClass("package org.junit.jupiter.api; public @interface Test {}"); + myFixture.addClass("package org.junit.jupiter.api; public @interface Nested {}"); + myFixture.configureByText("MyTest.java", text); + + new BaseGenerateTestSupportMethodAction.MyHandler(TestIntegrationUtils.MethodKind.TEST).invoke(myFixture.getProject(), + myFixture.getEditor(), + myFixture.getFile()); + myFixture.checkResult(expected); + } + ); + } +}