From 61d7019fb23b4c8d9d52934b8534cf196d359969 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 4 May 2015 16:28:33 +0200 Subject: [PATCH] junit/testng sm runner: open source at failure --- .../JavaAwareTestConsoleProperties.java | 36 +++++++++ .../testframework/sm/SMStacktraceParser.java | 2 + .../sm/SMStacktraceParserEx.java | 26 +++++++ .../sm/runner/SMTRunnerConsoleProperties.java | 11 ++- .../testframework/sm/runner/SMTestProxy.java | 5 +- .../junit/JUnitOpenSourceAtExceptionTest.java | 77 +++++++++++++++++++ 6 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParserEx.java create mode 100644 plugins/junit/test/com/intellij/execution/junit/JUnitOpenSourceAtExceptionTest.java diff --git a/java/execution/impl/src/com/intellij/execution/testframework/JavaAwareTestConsoleProperties.java b/java/execution/impl/src/com/intellij/execution/testframework/JavaAwareTestConsoleProperties.java index a88f15d5c6cf..d49624954ff0 100644 --- a/java/execution/impl/src/com/intellij/execution/testframework/JavaAwareTestConsoleProperties.java +++ b/java/execution/impl/src/com/intellij/execution/testframework/JavaAwareTestConsoleProperties.java @@ -24,14 +24,23 @@ import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.impl.DebuggerSession; import com.intellij.execution.CommonJavaRunConfigurationParameters; import com.intellij.execution.Executor; +import com.intellij.execution.Location; +import com.intellij.execution.PsiLocation; import com.intellij.execution.configurations.JavaRunConfigurationModule; import com.intellij.execution.configurations.ModuleBasedConfiguration; import com.intellij.execution.configurations.RunConfiguration; +import com.intellij.execution.stacktrace.StackTraceLine; import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties; +import com.intellij.openapi.diff.LineTokenizer; +import com.intellij.pom.Navigatable; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.tree.TreeSelectionModel; import java.util.Collection; +import java.util.Iterator; public abstract class JavaAwareTestConsoleProperties & CommonJavaRunConfigurationParameters> extends SMTRunnerConsoleProperties { public JavaAwareTestConsoleProperties(final String testFrameworkName, RunConfiguration configuration, Executor executor) { @@ -60,6 +69,33 @@ public abstract class JavaAwareTestConsoleProperties location, @NotNull String stacktrace) { + //navigate to the first stack trace + final String[] stackTrace = new LineTokenizer(stacktrace).execute(); + final PsiLocation psiLocation = location.toPsiLocation(); + final PsiClass containingClass = psiLocation.getParentElement(PsiClass.class); + if (containingClass == null) return null; + final String qualifiedName = containingClass.getQualifiedName(); + if (qualifiedName == null) return null; + String containingMethod = null; + for (Iterator> iterator = psiLocation.getAncestors(PsiMethod.class, false); iterator.hasNext();) { + final PsiMethod psiMethod = iterator.next().getPsiElement(); + if (containingClass.equals(psiMethod.getContainingClass())) containingMethod = psiMethod.getName(); + } + if (containingMethod == null) return null; + StackTraceLine lastLine = null; + for (String aStackTrace : stackTrace) { + final StackTraceLine line = new StackTraceLine(containingClass.getProject(), aStackTrace); + if (containingMethod.equals(line.getMethodName()) && qualifiedName.equals(line.getClassName())) { + lastLine = line; + break; + } + } + return lastLine != null ? lastLine.getOpenFileDescriptor(containingClass.getContainingFile().getVirtualFile()) : null; + } + @Nullable public DebuggerSession getDebugSession() { final DebuggerManagerEx debuggerManager = DebuggerManagerEx.getInstanceEx(getProject()); diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParser.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParser.java index 4016a3d389cd..8da1f65018b7 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParser.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParser.java @@ -22,7 +22,9 @@ import org.jetbrains.annotations.Nullable; /** * @author Roman.Chernyatchik + * @deprecated use {@link SMStacktraceParserEx} instead */ +@Deprecated public interface SMStacktraceParser { @Nullable Navigatable getErrorNavigatable(@NotNull Project project, @NotNull String stacktrace); diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParserEx.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParserEx.java new file mode 100644 index 000000000000..301285f96040 --- /dev/null +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMStacktraceParserEx.java @@ -0,0 +1,26 @@ +/* + * 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.intellij.execution.testframework.sm; + +import com.intellij.execution.Location; +import com.intellij.pom.Navigatable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface SMStacktraceParserEx extends SMStacktraceParser { + @Nullable + Navigatable getErrorNavigatable(@NotNull Location location, @NotNull String stacktrace); +} diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java index aec62fe1b861..d7445f3c043a 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java @@ -16,13 +16,14 @@ package com.intellij.execution.testframework.sm.runner; import com.intellij.execution.Executor; +import com.intellij.execution.Location; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.filters.CompositeFilter; import com.intellij.execution.filters.FileHyperlinkInfo; import com.intellij.execution.filters.Filter; import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.execution.testframework.TestConsoleProperties; -import com.intellij.execution.testframework.sm.SMStacktraceParser; +import com.intellij.execution.testframework.sm.SMStacktraceParserEx; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -42,7 +43,7 @@ import org.jetbrains.annotations.Nullable; /** * @author Roman Chernyatchik */ -public class SMTRunnerConsoleProperties extends TestConsoleProperties implements SMStacktraceParser { +public class SMTRunnerConsoleProperties extends TestConsoleProperties implements SMStacktraceParserEx { private final RunConfiguration myConfiguration; private final CompositeFilter myCustomFilter; private boolean myIdBasedTestTree = false; @@ -95,6 +96,12 @@ public class SMTRunnerConsoleProperties extends TestConsoleProperties implements myPrintTestingStartedTime = printTestingStartedTime; } + @Nullable + @Override + public Navigatable getErrorNavigatable(@NotNull Location location, @NotNull String stacktrace) { + return getErrorNavigatable(location.getProject(), stacktrace); + } + @Override public Navigatable getErrorNavigatable(@NotNull final Project project, final @NotNull String stacktrace) { if (myCustomFilter.isEmpty()) { diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index 65b21d27a05c..bdf9d9050542 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -18,6 +18,7 @@ package com.intellij.execution.testframework.sm.runner; import com.intellij.execution.Location; import com.intellij.execution.testframework.*; import com.intellij.execution.testframework.sm.SMStacktraceParser; +import com.intellij.execution.testframework.sm.SMStacktraceParserEx; import com.intellij.execution.testframework.sm.runner.states.*; import com.intellij.execution.testframework.sm.runner.ui.TestsPresentationUtil; import com.intellij.execution.testframework.stacktrace.DiffHyperlink; @@ -290,7 +291,9 @@ public class SMTestProxy extends AbstractTestProxy { String stacktrace = myStacktrace; if (stacktrace != null && properties instanceof SMStacktraceParser && isLeaf()) { - Navigatable result = ((SMStacktraceParser)properties).getErrorNavigatable(location.getProject(), stacktrace); + Navigatable result = properties instanceof SMStacktraceParserEx ? + ((SMStacktraceParserEx)properties).getErrorNavigatable(location, stacktrace) : + ((SMStacktraceParser)properties).getErrorNavigatable(location.getProject(), stacktrace); if (result != null) { return result; } diff --git a/plugins/junit/test/com/intellij/execution/junit/JUnitOpenSourceAtExceptionTest.java b/plugins/junit/test/com/intellij/execution/junit/JUnitOpenSourceAtExceptionTest.java new file mode 100644 index 000000000000..4229ccbd5215 --- /dev/null +++ b/plugins/junit/test/com/intellij/execution/junit/JUnitOpenSourceAtExceptionTest.java @@ -0,0 +1,77 @@ +/* + * 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.intellij.execution.junit; + +import com.intellij.execution.Location; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.junit2.info.MethodLocation; +import com.intellij.execution.junit2.ui.properties.JUnitConsoleProperties; +import com.intellij.execution.testframework.JavaTestLocator; +import com.intellij.execution.testframework.sm.runner.SMTestProxy; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.pom.Navigatable; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +public class JUnitOpenSourceAtExceptionTest extends LightCodeInsightFixtureTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + myFixture.addClass("package junit.framework; public class TestCase {}"); + } + + public void testStackTraceParseerAcceptsJavaStacktrace() throws Exception { + myFixture.addClass("abstract class ATest extends junit.framework.TestCase {" + + " public void testMe() {\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " int k = 0;\n" + + " fail();\n" + + " }\n" + + "}"); + myFixture.addClass("public class ChildTest extends ATest {}"); + + final SMTestProxy testProxy = new SMTestProxy("testMe", false, "java:test://ChildTest.testMe"); + testProxy.setTestFailed("failure", "\tat junit.framework.Assert.fail(Assert.java:57)\n" + + "\tat junit.framework.Assert.failNotEquals(Assert.java:329)\n" + + "\tat junit.framework.Assert.assertEquals(Assert.java:78)\n" + + "\tat junit.framework.Assert.assertEquals(Assert.java:234)\n" + + "\tat junit.framework.Assert.assertEquals(Assert.java:241)\n" + + "\tat junit.framework.TestCase.assertEquals(TestCase.java:409)\n" + + "\tat ATest.testMe(Dummy.java:6)\n", true); + final Project project = getProject(); + final GlobalSearchScope searchScope = GlobalSearchScope.projectScope(project); + testProxy.setLocator(JavaTestLocator.INSTANCE); + + final Location location = testProxy.getLocation(project, searchScope); + assertNotNull(location); + assertInstanceOf(location, MethodLocation.class); + + final JUnitConfiguration configuration = + new JUnitConfiguration("p", getProject(), JUnitConfigurationType.getInstance().getConfigurationFactories()[0]); + final Navigatable descriptor = + testProxy.getDescriptor(location, new JUnitConsoleProperties(configuration, DefaultRunExecutor.getRunExecutorInstance())); + assertInstanceOf(descriptor, OpenFileDescriptor.class); + final OpenFileDescriptor fileDescriptor = (OpenFileDescriptor)descriptor; + final VirtualFile file = fileDescriptor.getFile(); + assertNotNull(file); + assertEquals(5, fileDescriptor.getLine()); + } + +}