2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Created by IntelliJ IDEA.
23 package com
.theoryinpractice
.testng
.ui
;
25 import com
.intellij
.execution
.configurations
.ConfigurationPerRunnerSettings
;
26 import com
.intellij
.execution
.configurations
.RunnerSettings
;
27 import com
.intellij
.execution
.process
.ProcessHandler
;
28 import com
.intellij
.execution
.testframework
.ui
.BaseTestsOutputConsoleView
;
29 import com
.intellij
.execution
.testframework
.ui
.TestResultsPanel
;
30 import com
.intellij
.execution
.ui
.ConsoleView
;
31 import com
.intellij
.execution
.ui
.ConsoleViewContentType
;
32 import com
.intellij
.openapi
.application
.ApplicationManager
;
33 import com
.theoryinpractice
.testng
.configuration
.TestNGConfiguration
;
34 import com
.theoryinpractice
.testng
.model
.TestNGConsoleProperties
;
35 import com
.theoryinpractice
.testng
.model
.TestProxy
;
36 import org
.jetbrains
.annotations
.NonNls
;
37 import org
.testng
.remote
.strprotocol
.TestResultMessage
;
40 import java
.util
.ArrayList
;
41 import java
.util
.List
;
42 import java
.util
.regex
.Matcher
;
43 import java
.util
.regex
.Pattern
;
45 public class TestNGConsoleView
extends BaseTestsOutputConsoleView
{
46 @NonNls private static final Pattern COMPARISION_PATTERN
=
47 Pattern
.compile("([^\\<\\>]*)expected[^\\<\\>]*\\<([^\\<\\>]*)\\>[^\\<\\>]*\\<([^\\<\\>]*)\\>[^\\<\\>]*");
48 @NonNls private static final Pattern EXPECTED_BUT_WAS_PATTERN
=
49 Pattern
.compile("(.*)expected:\\<(.*)\\> but was:\\<(.*)\\>.*", Pattern
.DOTALL
);
50 @NonNls private static final Pattern EXPECTED_NOT_SAME_BUT_WAS_PATTERN
=
51 Pattern
.compile("(.*)expected not same with:\\<(.*)\\> but was:\\<(.*)\\>.*", Pattern
.DOTALL
);
52 private TestNGResults testNGResults
;
53 private final List
<Printable
> currentTestOutput
= new ArrayList
<Printable
>();
54 private final List
<Printable
> nonTestOutput
= new ArrayList
<Printable
>();
56 private int myExceptionalMark
= -1;
57 private final TestNGConfiguration myConfiguration
;
58 private final RunnerSettings myRunnerSettings
;
59 private final ConfigurationPerRunnerSettings myConfigurationPerRunnerSettings
;
61 public TestNGConsoleView(TestNGConfiguration config
,
62 final RunnerSettings runnerSettings
,
63 final ConfigurationPerRunnerSettings configurationPerRunnerSettings
) {
64 super(new TestNGConsoleProperties(config
));
65 myConfiguration
= config
;
66 myRunnerSettings
= runnerSettings
;
67 myConfigurationPerRunnerSettings
= configurationPerRunnerSettings
;
70 protected TestResultsPanel
createTestResultsPanel() {
71 testNGResults
= new TestNGResults(getConsole().getComponent(), myConfiguration
, this, myRunnerSettings
, myConfigurationPerRunnerSettings
);
77 public void dispose() {
82 public TestNGResults
getResultsView() {
86 public void rebuildTree() {
87 if (testNGResults
!= null) {
88 testNGResults
.rebuildTree();
92 public void addTestResult(TestResultMessage result
) {
93 if (testNGResults
!= null) {
94 if (!testNGResults
.wasTestStarted(result
)) {
97 int exceptionMark
= myExceptionalMark
== -1 ?
0 : myExceptionalMark
;
98 final String stackTrace
= result
.getStackTrace();
99 if (stackTrace
!= null && stackTrace
.length() > 10) {
100 //trim useless crud from stacktrace
101 String trimmed
= trimStackTrace(stackTrace
);
102 List
<Printable
> printables
= getPrintables(result
, trimmed
);
103 for (Printable printable
: printables
) {
104 printable
.print(getConsole()); //enable for root element
106 synchronized (currentTestOutput
) {
107 exceptionMark
= currentTestOutput
.size();
108 currentTestOutput
.addAll(printables
);
111 testNGResults
.addTestResult(result
, new ArrayList
<Printable
>(currentTestOutput
), exceptionMark
);
113 myExceptionalMark
= -1;
114 synchronized (currentTestOutput
) {
115 currentTestOutput
.clear();
120 public void testStarted(TestResultMessage result
) {
121 if (testNGResults
!= null) {
123 testNGResults
.testStarted(result
);
127 private void flushOutput() {
128 synchronized (currentTestOutput
) {
129 if (!currentTestOutput
.isEmpty()) { //non empty for first test only
130 nonTestOutput
.addAll(currentTestOutput
);
131 currentTestOutput
.clear();
136 public void flush() {
137 final TestProxy failedToStart
= testNGResults
.getFailedToStart();
138 if (failedToStart
!= null) {
139 final List
<Printable
> output
= failedToStart
.getOutput();
140 if (output
!= null) {
141 nonTestOutput
.addAll(output
);
146 private static String
trimStackTrace(String stackTrace
) {
147 String
[] lines
= stackTrace
.split("\n");
148 StringBuilder builder
= new StringBuilder();
150 if (lines
.length
> 0) {
151 int i
= lines
.length
- 1;
153 //first 4 chars are '\t at '
154 int startIndex
= lines
[i
].indexOf('a') + 3;
155 if (lines
[i
].length() > 4 &&
156 (lines
[i
].startsWith("org.testng.", startIndex
) ||
157 lines
[i
].startsWith("org.junit.", startIndex
) ||
158 lines
[i
].startsWith("sun.reflect.DelegatingMethodAccessorImpl", startIndex
) ||
159 lines
[i
].startsWith("sun.reflect.NativeMethodAccessorImpl", startIndex
) ||
160 lines
[i
].startsWith("java.lang.reflect.Method", startIndex
) ||
161 lines
[i
].startsWith("com.intellij.rt.execution.application.AppMain", startIndex
))) {
165 // we're done with internals, so we know the rest are ok
170 for (int j
= 0; j
<= i
; j
++) {
171 builder
.append(lines
[j
]);
172 builder
.append('\n');
175 return builder
.toString();
178 private List
<Printable
> getPrintables(final TestResultMessage result
, String s
) {
179 List
<Printable
> printables
= new ArrayList
<Printable
>();
180 //figure out if we have a diff we need to hyperlink
181 Matcher matcher
= COMPARISION_PATTERN
.matcher(s
);
182 if (!matcher
.matches()) {
183 matcher
= EXPECTED_BUT_WAS_PATTERN
.matcher(s
);
185 if (!matcher
.matches()) {
186 matcher
= EXPECTED_NOT_SAME_BUT_WAS_PATTERN
.matcher(s
);
188 if (matcher
.matches()) {
189 printables
.add(new Chunk(matcher
.group(1), ConsoleViewContentType
.ERROR_OUTPUT
));
190 //we have an assert with expected/actual, so we parse it out and create a diff hyperlink
191 TestNGDiffHyperLink link
= new TestNGDiffHyperLink(matcher
.group(2), matcher
.group(3), null, (TestNGConsoleProperties
) myProperties
) {
192 protected String
getTitle() {
193 //TODO should do some more farting about to find the equality assertion that failed and show that as title
194 return result
.getTestClass() + '#' + result
.getMethod() + "() failed";
197 //same as junit diff view
198 printables
.add(link
);
199 printables
.add(new Chunk(trimStackTrace(s
.substring(matcher
.end(3) + 1)), ConsoleViewContentType
.ERROR_OUTPUT
));
202 printables
.add(new Chunk(s
, ConsoleViewContentType
.ERROR_OUTPUT
));
207 public void print(String s
, ConsoleViewContentType contentType
) {
208 if (myExceptionalMark
== -1 && contentType
== ConsoleViewContentType
.ERROR_OUTPUT
) {
209 myExceptionalMark
= currentTestOutput
.size();
211 Chunk chunk
= new Chunk(s
, contentType
);
212 synchronized (currentTestOutput
) {
213 currentTestOutput
.add(chunk
);
217 public void reset() {
218 final List
<Printable
> printables
= new ArrayList
<Printable
>();
219 printables
.addAll(nonTestOutput
);
220 printables
.addAll(testNGResults
.getRoot().getOutput());
221 printables
.addAll(currentTestOutput
);
222 setView(printables
, 0);
225 public void attachToProcess(ProcessHandler processHandler
) {
226 getConsole().attachToProcess(processHandler
);
229 public void setView(final List
<Printable
> output
, final int i
) {
230 if (!ApplicationManager
.getApplication().isDispatchThread()) {
231 SwingUtilities
.invokeLater(new Runnable() {
238 getConsole().clear();
241 for (Printable chunk
: new ArrayList
<Printable
>(output
)) {
242 chunk
.print(getConsole());
244 offset
= getConsole().getContentSize();
247 getConsole().scrollTo(offset
);
251 public static class Chunk
implements Printable
{
253 public ConsoleViewContentType contentType
;
255 public void print(ConsoleView console
) {
256 console
.print(text
, contentType
);
259 public Chunk(String text
, ConsoleViewContentType contentType
) {
261 this.contentType
= contentType
;
264 public String
toString() {