diff --git a/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java b/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java index e8e27118cb44..a8177102ae2e 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java @@ -22,7 +22,7 @@ import java.util.List; public class CompositePrintable implements Printable { public static final String NEW_LINE = "\n"; - private final ArrayList myNestedPrintables = new ArrayList(); + protected final ArrayList myNestedPrintables = new ArrayList(); public void printOn(final Printer printer) { printAllOn(myNestedPrintables, printer); diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java index 93f14f39c44d..9adb1a1e2a33 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java @@ -31,9 +31,7 @@ import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; -import com.intellij.execution.testframework.TestConsoleProperties; -import com.intellij.execution.testframework.TestFrameworkRunningModel; -import com.intellij.execution.testframework.TestSearchScope; +import com.intellij.execution.testframework.*; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.execution.util.JavaParametersUtil; import com.intellij.openapi.application.PathManager; @@ -60,10 +58,7 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.pom.java.LanguageLevel; import com.intellij.util.PathUtil; import com.intellij.util.net.NetUtils; -import com.theoryinpractice.testng.model.IDEARemoteTestRunnerClient; -import com.theoryinpractice.testng.model.TestData; -import com.theoryinpractice.testng.model.TestNGRemoteListener; -import com.theoryinpractice.testng.model.TestType; +import com.theoryinpractice.testng.model.*; import com.theoryinpractice.testng.ui.TestNGConsoleView; import com.theoryinpractice.testng.ui.TestNGResults; import com.theoryinpractice.testng.ui.actions.RerunFailedTestsAction; @@ -131,7 +126,8 @@ public class TestNGRunnableState extends JavaCommandLineState { } throw e; } - final TestNGConsoleView console = new TestNGConsoleView(config, runnerSettings, myConfigurationPerRunnerSettings); + final TreeRootNode unboundOutputRoot = new TreeRootNode(); + final TestNGConsoleView console = new TestNGConsoleView(config, runnerSettings, myConfigurationPerRunnerSettings, unboundOutputRoot); console.initUI(); for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) { ext.handleStartProcess(config, processHandler); @@ -166,8 +162,9 @@ public class TestNGRunnableState extends JavaCommandLineState { @Override public void startNotified(final ProcessEvent event) { - TestNGRemoteListener listener = new TestNGRemoteListener(console); + TestNGRemoteListener listener = new TestNGRemoteListener(console, unboundOutputRoot); client.startListening(listener, listener, port); + } @Override @@ -180,9 +177,20 @@ public class TestNGRunnableState extends JavaCommandLineState { @Override public void onTextAvailable(final ProcessEvent event, final Key outputType) { - //we override this since we wrap the underlying console, and proxy the attach call, - //so we never get a chance to intercept the text. - console.print(event.getText(), ConsoleViewContentType.getConsoleViewType(outputType)); + final TestProxy currentTest = console.getCurrentTest(); + final String text = event.getText(); + final ConsoleViewContentType consoleViewType = ConsoleViewContentType.getConsoleViewType(outputType); + final Printable printable = new Printable() { + public void printOn(final Printer printer) { + printer.print(text, consoleViewType); + } + }; + if (currentTest != null) { + currentTest.addLast(printable); + } + else { + unboundOutputRoot.addLast(printable); + } } }); console.attachToProcess(processHandler); diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGRemoteListener.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGRemoteListener.java index 5bd7e5f3d89e..eaec7f802dcc 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGRemoteListener.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGRemoteListener.java @@ -27,58 +27,60 @@ import com.theoryinpractice.testng.ui.TestNGResults; import org.testng.remote.strprotocol.*; public class TestNGRemoteListener implements IRemoteSuiteListener, IRemoteTestListener { - private final TestNGConsoleView console; + private final TestNGConsoleView console; + private final TreeRootNode unboundOutputRoot; - public TestNGRemoteListener(TestNGConsoleView console) { - this.console = console; - } + public TestNGRemoteListener(TestNGConsoleView console, TreeRootNode unboundOutputRoot) { + this.console = console; + this.unboundOutputRoot = unboundOutputRoot; + } - public void onInitialization(GenericMessage genericMessage) { - } + public void onInitialization(GenericMessage genericMessage) { + } - public void onStart(SuiteMessage suiteMessage) { - console.flushOutput(); - final TestNGResults view = console.getResultsView(); - if (view != null) { - view.start(); - } + public void onStart(SuiteMessage suiteMessage) { + final TestNGResults view = console.getResultsView(); + if (view != null) { + view.start(); } + } - public void onFinish(SuiteMessage suiteMessage) { - console.flush(); - final TestNGResults view = console.getResultsView(); - if (view != null) { - view.finish(); - } + public void onFinish(SuiteMessage suiteMessage) { + console.finish(); + final TestNGResults view = console.getResultsView(); + if (view != null) { + view.finish(); } + } - public void onStart(TestMessage tm) { - final TestNGResults view = console.getResultsView(); - if (view != null) { - view.setTotal(tm.getTestMethodCount()); - } + public void onStart(TestMessage tm) { + unboundOutputRoot.addChild(console.getResultsView().getRoot()); + final TestNGResults view = console.getResultsView(); + if (view != null) { + view.setTotal(tm.getTestMethodCount()); } + } - public void onTestStart(TestResultMessage trm) { - console.testStarted(trm); - } + public void onTestStart(TestResultMessage trm) { + console.testStarted(trm); + } - public void onFinish(TestMessage tm) { - console.rebuildTree(); - } + public void onFinish(TestMessage tm) { + console.rebuildTree(); + } - public void onTestSuccess(TestResultMessage trm) { - console.addTestResult(trm); - } + public void onTestSuccess(TestResultMessage trm) { + console.addTestResult(trm); + } - public void onTestFailure(TestResultMessage trm) { - console.addTestResult(trm); - } + public void onTestFailure(TestResultMessage trm) { + console.addTestResult(trm); + } - public void onTestSkipped(TestResultMessage trm) { - console.addTestResult(trm); - } + public void onTestSkipped(TestResultMessage trm) { + console.addTestResult(trm); + } - public void onTestFailedButWithinSuccessPercentage(TestResultMessage trm) { - } + public void onTestFailedButWithinSuccessPercentage(TestResultMessage trm) { + } } diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java index 8241c28c409e..b3ab68e164dd 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java @@ -47,7 +47,6 @@ public class TestProxy extends AbstractTestProxy { private TestResultMessage resultMessage; private String name; private TestProxy parent; - private List output; private SmartPsiElementPointer psiElement; private boolean inProgress; private int myExceptionMark; @@ -86,19 +85,6 @@ public class TestProxy extends AbstractTestProxy { return filter.select(results); } - public List getOutput() { - if (output != null) return output; - List total = new ArrayList(); - for (TestProxy child : results) { - final List out = child.getOutput(); - if (total.size() > 0 && out.size() > 0) { - total.add(new TestNGConsoleView.Chunk("\n===============================================\n\n", ConsoleViewContentType.NORMAL_OUTPUT)); - } - total.addAll(out); - } - return total; - } - public List getChildren() { return results; } @@ -170,7 +156,7 @@ public class TestProxy extends AbstractTestProxy { public Navigatable getDescriptor(final Location location) { if (location == null) return null; - if (isNotPassed() && output != null) { + if (isNotPassed()) { final PsiLocation psiLocation = location.toPsiLocation(); final PsiClass containingClass = psiLocation.getParentElement(PsiClass.class); if (containingClass != null) { @@ -181,7 +167,7 @@ public class TestProxy extends AbstractTestProxy { } if (containingMethod != null) { final String qualifiedName = containingClass.getQualifiedName(); - for (Printable aStackTrace : output) { + for (Printable aStackTrace : myNestedPrintables) { if (aStackTrace instanceof TestNGConsoleView.Chunk) { final String[] stackTrace = new LineTokenizer(((TestNGConsoleView.Chunk)aStackTrace).text).execute(); for (String line : stackTrace) { @@ -203,9 +189,10 @@ public class TestProxy extends AbstractTestProxy { return name + ' ' + results; } - public void addResult(TestProxy proxy) { + public void addChild(TestProxy proxy) { results.add(proxy); proxy.setParent(this); + addLast(proxy); } public void setParent(TestProxy parent) { @@ -216,10 +203,6 @@ public class TestProxy extends AbstractTestProxy { return parent; } - public void setOutput(List output) { - this.output = output; - } - public boolean isNotPassed() { if (resultNotPassed()) return true; //we just added the node, so we don't know if it has passes or fails @@ -260,9 +243,9 @@ public class TestProxy extends AbstractTestProxy { return null; } - public int getExceptionMark() { + public int getExceptionMark() {//todo if (myExceptionMark == 0 && getChildCount() > 0) { - return (output != null ? output.size() : 0) + getChildAt(0).getExceptionMark(); + return getChildAt(0).getExceptionMark(); } return myExceptionMark; } diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestTreeBuilder.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestTreeBuilder.java index 531b249228b1..1bf037826de8 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestTreeBuilder.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestTreeBuilder.java @@ -50,7 +50,7 @@ public class TestTreeBuilder extends AbstractTestTreeBuilder } public void addItem(TestProxy parent, TestProxy proxy) { - parent.addResult(proxy); + parent.addChild(proxy); DefaultMutableTreeNode parentNode = getNodeForElement(parent); if (parentNode != null) updateSubtree(parentNode); diff --git a/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGConsoleView.java b/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGConsoleView.java index 129721c3668d..428cfa97feed 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGConsoleView.java +++ b/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGConsoleView.java @@ -28,6 +28,7 @@ import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.testframework.Printable; import com.intellij.execution.testframework.Printer; +import com.intellij.execution.testframework.TestTreeView; import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView; import com.intellij.execution.testframework.ui.TestResultsPanel; @@ -37,10 +38,13 @@ import com.intellij.openapi.application.ApplicationManager; import com.theoryinpractice.testng.configuration.TestNGConfiguration; import com.theoryinpractice.testng.model.TestNGConsoleProperties; import com.theoryinpractice.testng.model.TestProxy; +import com.theoryinpractice.testng.model.TreeRootNode; import org.jetbrains.annotations.NonNls; import org.testng.remote.strprotocol.TestResultMessage; import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -54,8 +58,7 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView { @NonNls private static final Pattern EXPECTED_NOT_SAME_BUT_WAS_PATTERN = Pattern.compile("(.*)expected not same with:\\<(.*)\\> but was:\\<(.*)\\>.*", Pattern.DOTALL); private TestNGResults testNGResults; - private final List currentTestOutput = new ArrayList(); - private final List nonTestOutput = new ArrayList(); + private TestProxy currentTest; private int myExceptionalMark = -1; private final TestNGConfiguration myConfiguration; @@ -64,8 +67,9 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView { public TestNGConsoleView(TestNGConfiguration config, final RunnerSettings runnerSettings, - final ConfigurationPerRunnerSettings configurationPerRunnerSettings) { - super(new TestNGConsoleProperties(config), null); + final ConfigurationPerRunnerSettings configurationPerRunnerSettings, + final TreeRootNode unboundOutputRoot) { + super(new TestNGConsoleProperties(config), unboundOutputRoot); myConfiguration = config; myRunnerSettings = runnerSettings; myConfigurationPerRunnerSettings = configurationPerRunnerSettings; @@ -76,6 +80,16 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView { return testNGResults; } + @Override + public void initUI() { + super.initUI(); + final TestTreeView testTreeView = testNGResults.getTreeView(); + testTreeView.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + getPrinter().updateOnTestSelected(testTreeView.getSelectedTest()); + } + }); + } @Override public void dispose() { @@ -96,50 +110,30 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView { public void addTestResult(TestResultMessage result) { if (testNGResults != null) { int exceptionMark = myExceptionalMark == -1 ? 0 : myExceptionalMark; + final String stackTrace = result.getStackTrace(); if (stackTrace != null && stackTrace.length() > 10) { //trim useless crud from stacktrace String trimmed = trimStackTrace(stackTrace); List printables = getPrintables(result, trimmed); for (Printable printable : printables) { - printable.printOn(wrapConsoleView(getConsole())); //enable for root element - } - synchronized (currentTestOutput) { - exceptionMark = currentTestOutput.size(); - currentTestOutput.addAll(printables); + currentTest.addLast(printable); } + exceptionMark = printables.size(); } - testNGResults.addTestResult(result, new ArrayList(currentTestOutput), exceptionMark); - + final TestProxy failedToStart = testNGResults.getFailedToStart(); + if (failedToStart != null) { + currentTest.addChild(failedToStart); + exceptionMark += failedToStart.getExceptionMark(); + } + testNGResults.addTestResult(result, exceptionMark); myExceptionalMark = -1; - synchronized (currentTestOutput) { - currentTestOutput.clear(); - } } } public void testStarted(TestResultMessage result) { if (testNGResults != null) { - testNGResults.testStarted(result); - } - } - - public void flushOutput() { - synchronized (currentTestOutput) { - if (!currentTestOutput.isEmpty()) { //non empty for first test only - nonTestOutput.addAll(currentTestOutput); - currentTestOutput.clear(); - } - } - } - - public void flush() { - final TestProxy failedToStart = testNGResults.getFailedToStart(); - if (failedToStart != null) { - final List output = failedToStart.getOutput(); - if (output != null) { - nonTestOutput.addAll(output); - } + currentTest = testNGResults.testStarted(result); } } @@ -204,66 +198,15 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView { return printables; } - public void print(String s, ConsoleViewContentType contentType) { - if (myExceptionalMark == -1 && contentType == ConsoleViewContentType.ERROR_OUTPUT) { - myExceptionalMark = currentTestOutput.size(); - } - Chunk chunk = new Chunk(s, contentType); - synchronized (currentTestOutput) { - currentTestOutput.add(chunk); - } - } - - public void reset() { - final List printables = new ArrayList(); - printables.addAll(nonTestOutput); - printables.addAll(testNGResults.getRoot().getOutput()); - printables.addAll(currentTestOutput); - setView(printables, 0); - } - public void attachToProcess(ProcessHandler processHandler) { - getConsole().attachToProcess(processHandler); - } - - public void setView(final List output, final int i) { - if (!ApplicationManager.getApplication().isDispatchThread()) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - setView(output, i); - } - }); - } - else { - final ConsoleView consoleView = getConsole(); - consoleView.clear(); - int idx = 0; - int offset = 0; - for (Printable chunk : new ArrayList(output)) { - chunk.printOn(wrapConsoleView(consoleView)); - if (idx++ < i) { - offset = consoleView.getContentSize(); - } - } - consoleView.scrollTo(offset); - } } - private static Printer wrapConsoleView(final ConsoleView consoleView) { - return new Printer() { - public void print(String text, ConsoleViewContentType contentType) { - consoleView.print(text, contentType); - } + public TestProxy getCurrentTest() { + return currentTest; + } - public void onNewAvailable(Printable printable) {} - - public void printHyperlink(String text, HyperlinkInfo info) { - consoleView.printHyperlink(text, info); - } - - public void mark() { - } - }; + public void finish() { + currentTest = null; } public static class Chunk implements Printable { diff --git a/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java b/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java index d6c45d8b1649..d137b3739d14 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java +++ b/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java @@ -81,7 +81,6 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn private final TreeRootNode rootNode; private static final String NO_PACKAGE = "No Package"; private TestNGResults.OpenSourceSelectionListener openSourceListener; - private final TestNGConsoleView myConsole; private int myStatus = MessageHelper.PASSED_TEST; private Set startedMethods = new HashSet(); @@ -92,7 +91,6 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn final ConfigurationPerRunnerSettings configurationSettings) { super(component, console.createConsoleActions(), console.getProperties(), runnerSettings, configurationSettings, TESTNG_SPLITTER_PROPERTY, 0.5f); - myConsole = console; this.project = configuration.getProject(); model = new TestNGResultsTableModel(); @@ -132,7 +130,7 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn animator = new Animator(this, treeBuilder); - openSourceListener = new OpenSourceSelectionListener(structure, myConsole); + openSourceListener = new OpenSourceSelectionListener(); tree.getSelectionModel().addTreeSelectionListener(openSourceListener); return tree; @@ -218,11 +216,8 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn return proxy; } - public void addTestResult(final TestResultMessage result, List output, int exceptionMark) { - if (failedToStart != null) { - output.addAll(failedToStart.getOutput()); - exceptionMark += failedToStart.getExceptionMark(); - } + public void addTestResult(final TestResultMessage result, int exceptionMark) { + TestProxy testCase; synchronized (started) { @@ -261,7 +256,6 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn failedToStart = testCase; } - testCase.setOutput(output); testCase.setExceptionMark(exceptionMark); if (result.getResult() == MessageHelper.FAILED_TEST) { @@ -415,8 +409,6 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn public void dispose() { super.dispose(); - openSourceListener.structure = null; - openSourceListener.console = null; tree.getSelectionModel().removeTreeSelectionListener(openSourceListener); } @@ -425,13 +417,6 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn } private class OpenSourceSelectionListener implements TreeSelectionListener { - private TestTreeStructure structure; - private TestNGConsoleView console; - - public OpenSourceSelectionListener(TestTreeStructure structure, TestNGConsoleView console) { - this.structure = structure; - this.console = console; - } public void valueChanged(TreeSelectionEvent e) { TreePath path = e.getPath(); @@ -441,13 +426,6 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn if (ScrollToTestSourceAction.isScrollEnabled(TestNGResults.this)) { OpenSourceUtil.openSourcesFrom(tree, false); } - if (proxy == structure.getRootElement()) { - console.reset(); - } - else { - console - .setView(proxy.getOutput(), TestNGConsoleProperties.SCROLL_TO_STACK_TRACE.value(getProperties()) ? proxy.getExceptionMark() : 0); - } } } }