package com.softwaremill.common.test.web.selenium.testng;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
/**
* Reports tests on the fly for TeamCity
*/
public class TeamcityTestNGNotifier extends TestListenerAdapter {
public static final String TEST_STARTED = "##teamcity[testStarted name='%1$s' captureStandardOutput='true']";
public static final String TEST_ENDED = "##teamcity[testFinished name='%1$s' duration='%2$s']";
public static final String TEST_FAILED = "##teamcity[testFailed name='%1$s' message='%2$s' details='%3$s']";
private static final Set<String> startedTests = new HashSet<String>();
private static final Set<String> finishedTests = new HashSet<String>();
private String[][] charsToReplace = new String[][]{
new String[]{"|", "||"},
new String[]{"'", "|'"},
new String[]{"\n", "|n"},
new String[]{"\r", "|r"},
new String[]{"\u0085", "|x"},
new String[]{"\u2028", "|l"},
new String[]{"\u2029", "|p"},
new String[]{"[", "|["},
new String[]{"]", "|]"}
};
@Override
public void onTestSuccess(ITestResult result) {
String testName = getTestName(result);
if (!finishedTests.contains(testName)) {
finishedTests.add(testName);
System.out.println(String.format(TEST_ENDED, escapeForTeamcity(testName),
result.getEndMillis() - result.getStartMillis()));
}
}
@Override
public void onTestStart(ITestResult result) {
String testName = getTestName(result);
if (!startedTests.contains(testName)) {
startedTests.add(testName);
System.out.println(String.format(TEST_STARTED, escapeForTeamcity(testName)));
}
}
@Override
public void onTestFailure(ITestResult result) {
String testName = getTestName(result);
if (!finishedTests.contains(testName)) {
finishedTests.add(testName);
// get the stacktrace first
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
result.getThrowable().printStackTrace(pw);
System.out.println(String.format(TEST_FAILED, escapeForTeamcity(testName),
escapeForTeamcity(result.getThrowable().getMessage()),
escapeForTeamcity(sw.toString())
));
// and mark test finished
onTestSuccess(result);
}
}
private String getTestName(ITestResult result) {
return result.getTestClass().getName() + "." + result.getName();
}
private String escapeForTeamcity(String string) {
// more info http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingTests
if (string != null) {
for (String[] chars : charsToReplace) {
string = string.replace(chars[0], chars[1]);
}
}
return string;
}
}