/*
* JBoss, Home of Professional Open Source
* Copyright 2010-2016, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.selenium.listener;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.jboss.arquillian.drone.api.annotation.Default;
import org.jboss.arquillian.graphene.context.GrapheneContext;
import org.jboss.arquillian.graphene.proxy.GrapheneProxyInstance;
import org.jboss.test.selenium.utils.testng.TestInfo;
import org.jboss.test.selenium.utils.testng.TestLoggingUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
/**
* Test listener which provides the methods injected in lifecycle of test case to catch the additional information in context of
* test failure.
*
* @author <a href="mailto:lfryc@redhat.com">Lukas Fryc</a>
* @author <a href="https://community.jboss.org/people/ppitonak">Pavol Pitonak</a>
* @version $Revision$
*/
public class FailureLoggingTestListener extends TestListenerAdapter {
// protected static final Logger LOGGER = Logger.getLogger(FailureLoggingTestListener.class.getName());
protected File mavenProjectBuildDirectory = new File(System.getProperty("maven.project.build.directory",
"./target/"));
protected File failuresOutputDir = new File(mavenProjectBuildDirectory, "failures");
@Override
public void onStart(ITestContext testContext) {
try {
FileUtils.forceMkdir(failuresOutputDir);
// FIXME it should clean directory only if it is the first test suite
// FileUtils.cleanDirectory(failuresOutputDir);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void onConfigurationFailure(ITestResult result) {
saveStackTrace(result);
}
@Override
public void onTestFailure(ITestResult result) {
saveStackTrace(result);
saveScreenshotAndPageSource(result);
}
/**
* Mark all lines beginning with 'at org.richfaces'
*/
private String markStackTrace(String stackTrace) {
StringBuilder sb = new StringBuilder();
String toFind = "at org.richfaces";
String newLine = "\n";
String tabulator = "\t";
String mark = " --> ";
for (String line : stackTrace.split(newLine)) {
if (line.contains(toFind)) {
sb.append(line.replace(tabulator, mark));
} else {
sb.append(line);
}
sb.append(newLine);
}
return sb.toString();
}
private void saveStackTrace(ITestResult result) {
Throwable throwable = result.getThrowable();
String stacktrace = null;
if (throwable != null) {
stacktrace = markStackTrace(ExceptionUtils.getStackTrace(throwable));
}
String filenameIdentification = getFilenameIdentification(result);
File outputFile = new File(failuresOutputDir, filenameIdentification + "/stacktrace.txt");
File directory = outputFile.getParentFile();
try {
FileUtils.forceMkdir(directory);
FileUtils.writeStringToFile(outputFile, stacktrace);
} catch (IOException e) {
System.err.println("Can't create directory or save file with stack trace: " + e.getMessage());
e.printStackTrace(System.err);
}
}
public void saveScreenshotAndPageSource(ITestResult result) {
if (getWebDriver() == null) {
System.out.println("Can't take a screenshot and save HTML, because there is no driver available.");
return;
}
String filenameIdentification = getFilenameIdentification(result);
// TODO traffic can be captured using BrowserMob Proxy
// String traffic;
// try {
// traffic = selenium.captureNetworkTraffic(NetworkTrafficType.PLAIN).getTraffic();
// } catch (SeleniumException e) {
// traffic = ExceptionUtils.getFullStackTrace(e);
// }
try {
File screenshot = null;
if (((GrapheneProxyInstance) getWebDriver()).unwrap() instanceof TakesScreenshot) {
screenshot = ((TakesScreenshot) getWebDriver()).getScreenshotAs(OutputType.FILE);
}
String htmlSource = getWebDriver().getPageSource();
File imageOutputFile = new File(failuresOutputDir, filenameIdentification + "/screenshot.png");
// File trafficOutputFile = new File(failuresOutputDir, filenameIdentification + "/network-traffic.txt");
// File logOutputFile = new File(failuresOutputDir, filenameIdentification + "/selenium-log.txt");
File htmlSourceOutputFile = new File(failuresOutputDir, filenameIdentification + "/html-source.html");
File directory = imageOutputFile.getParentFile();
FileUtils.forceMkdir(directory);
FileUtils.copyFile(screenshot, imageOutputFile);
// FileUtils.writeStringToFile(trafficOutputFile, traffic);
// FileUtils.writeLines(logOutputFile, methodLog);
FileUtils.writeStringToFile(htmlSourceOutputFile, htmlSource);
} catch (IOException e) {
System.err.println("Can't take a screenshot/save HTML source: " + e.getMessage());
e.printStackTrace(System.err);
// LOGGER.log(Level.WARNING, "Can't take a screenshot/save HTML source.", e);
}
}
protected String getSeleniumLogIdentification(ITestResult result) {
final String failure = TestInfo.STATUSES.get(result.getStatus()).toUpperCase();
final String started = TestInfo.STATUSES.get(ITestResult.STARTED).toUpperCase();
String testDescription = TestLoggingUtils.getTestDescription(result);
testDescription = testDescription.replaceFirst(failure, started);
testDescription = testDescription.replaceFirst("\\[[^\\]]+\\] ", "");
return testDescription;
}
protected String getFilenameIdentification(ITestResult result) {
return TestInfo.getClassMethodName(result);
}
protected WebDriver getWebDriver() {
return GrapheneContext.getContextFor(Default.class).getWebDriver(TakesScreenshot.class);
}
}