/*
* Copyright 2009 Google Inc.
*
* 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.google.jstestdriver;
import com.google.gson.Gson;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author jeremiele@google.com (Jeremie Lenfant-Engelmann)
*/
public class DefaultPrinter implements TestResultPrinter {
private static final String NEW_LINE = System.getProperty("line.separator");
private final Gson gson = new Gson();
private final PrintStream out;
private final AtomicInteger browsers;
private final boolean verbose;
private final Map<String, RunData> browsersRunData = new ConcurrentHashMap<String, RunData>();
private final AtomicInteger lineColumn = new AtomicInteger(0);
private final AtomicInteger totalPasses = new AtomicInteger(0);
private final AtomicInteger totalFails = new AtomicInteger(0);
private final AtomicInteger totalErrors = new AtomicInteger(0);
private int lineLength = 70;
public DefaultPrinter(PrintStream out, int browsers, boolean verbose) {
this.out = out;
this.browsers = new AtomicInteger(browsers);
this.verbose = verbose;
}
public void setLineLength(int lineLength) {
this.lineLength = lineLength;
}
public void open() {
}
public void open(String name) {
}
public void close() {
if (browsers.decrementAndGet() == 0) {
if (!verbose) {
out.println();
}
out.println(String.format("Total %d tests (Passed: %d; Fails: %d; Errors: %d) (%.2f ms)",
(totalPasses.get() + totalFails.get() + totalErrors.get()), totalPasses.get(),
totalFails.get(), totalErrors.get(), findMaxTime()));
for (Map.Entry<String, RunData> entry : browsersRunData.entrySet()) {
RunData data = entry.getValue();
out.println(String.format(" %s: Run %d tests (Passed: %d; Fails: %d; Errors %d) (%.2f ms)",
entry.getKey(), (data.getPassed() + data.getFailed() + data.getErrors()),
data.getPassed(), data.getFailed(), data.getErrors(), data.getTotalTime()));
List<TestResult> problems = data.getProblems();
for (TestResult testResult : problems) {
if (!testResult.getResult().equals("passed")) {
String message = "";
String stack = "";
try {
// TODO(jeremiele): do a better job at parsing the stack.
JsException exception = gson.fromJson(testResult.getMessage(), JsException.class);
message = exception.getMessage();
String errorStack = exception.getStack();
String[] lines = errorStack.split("\n");
String errorLine = "";
for (String l : lines) {
if (l.contains("/test/")) {
errorLine += NEW_LINE + " " + l;
}
}
if (errorLine.length() > 0) {
stack = errorLine;
}
} catch (Exception e) {
message = testResult.getMessage();
}
out.println(String.format(" %s.%s %s (%.2f ms): %s%s", testResult.getTestCaseName(),
testResult.getTestName(), testResult.getResult(), testResult.getTime(), message,
stack));
} else {
out.println(String.format(" %s.%s %s (%.2f ms)", testResult.getTestCaseName(),
testResult.getTestName(), testResult.getResult(), testResult.getTime()));
}
if (!verbose && testResult.getLog().length() > 0) {
String[] logLines = testResult.getLog().split("\n");
for (String line : logLines) {
out.println(" " + line);
}
}
}
}
}
}
private float findMaxTime() {
float max = 0f;
for (RunData data : browsersRunData.values()) {
max = Math.max(data.getTotalTime(), max);
}
return max;
}
public void print(TestResult testResult) {
String browserName = testResult.getBrowserInfo().getName();
String browserVersion = testResult.getBrowserInfo().getVersion();
String os = testResult.getBrowserInfo().getOs();
RunData runData = browsersRunData.get(browserName + " " + browserVersion + " " + os);
if (runData == null) {
runData = new RunData();
browsersRunData.put(browserName + " " + browserVersion + " " + os, runData);
}
String result = testResult.getResult();
String log = testResult.getLog();
runData.addTime(testResult.getTime());
if (result.equals("passed")) {
if (!verbose) {
out.print('.');
if (log.length() > 0) {
runData.addProblem(testResult);
}
} else {
out.println("[PASSED] " + testResult.getTestCaseName() + "." + testResult.getTestName());
if (log.length() > 0) {
String[] logLines = log.split("\n");
for (String line : logLines) {
out.println(" " + line);
}
}
}
runData.addPass();
totalPasses.incrementAndGet();
} else if (result.startsWith("failed")) {
if (!verbose) {
out.print('F');
} else {
out.println("[FAILED] " + testResult.getTestCaseName() + "." + testResult.getTestName());
if (log.length() > 0) {
String[] logLines = log.split("\n");
for (String line : logLines) {
out.println(" " + line);
}
}
}
runData.addFail();
runData.addProblem(testResult);
totalFails.incrementAndGet();
} else if (result.startsWith("error")) {
if (!verbose) {
out.print('E');
} else {
out.println("[ERROR] " + testResult.getTestCaseName() + "." + testResult.getTestName());
if (log.length() > 0) {
String[] logLines = log.split("\n");
for (String line : logLines) {
out.println(" " + line);
}
}
}
runData.addError();
runData.addProblem(testResult);
totalErrors.incrementAndGet();
} else {
out.print("<" + result + ">");
if (verbose) {
out.println(" " + testResult.getTestCaseName() + "." + testResult.getTestName());
if (log.length() > 0) {
String[] logLines = log.split("\n");
for (String line : logLines) {
out.println(" " + line);
}
}
}
runData.addProblem(testResult);
}
if (lineColumn.incrementAndGet() == lineLength) {
out.println();
lineColumn.set(0);
}
}
}