/*
* (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library 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.
*
* Contributors:
* <a href="mailto:grenard@nuxeo.com">Guillaume</a>
*/
package org.nuxeo.functionaltests;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.nuxeo.common.utils.URIUtils;
import org.openqa.selenium.remote.RemoteWebDriver;
/**
* Watchman to log info about the test and create snapshot on failure.
*
* @since 5.8
*/
public class LogTestWatchman extends TestWatchman {
protected static final Log log = LogFactory.getLog(AbstractTest.class);
protected String lastScreenshot;
protected String lastPageSource;
protected String filePrefix;
protected RemoteWebDriver driver;
protected String serverURL;
public LogTestWatchman(final RemoteWebDriver driver, final String serverURL) {
this.driver = driver;
this.serverURL = serverURL;
}
public LogTestWatchman() {
}
@Override
@SuppressWarnings("unchecked")
public Statement apply(final Statement base, final FrameworkMethod method,
Object target) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
starting(method);
try {
if (base instanceof RunAfters) {
// Hack JUnit: in order to take screenshot at the right
// time we add through reflection an after
// function that will be executed before all other
// ones. See NXP-12742
Field fAtersField = RunAfters.class.getDeclaredField("fAfters");
fAtersField.setAccessible(true);
List<FrameworkMethod> afters = (List<FrameworkMethod>) fAtersField.get(base);
if (afters != null && !afters.isEmpty()) {
try {
// Improve this and instead of finding a
// special function, we could register
// functions specially annotated.
FrameworkMethod first = afters.get(0);
Method m = AbstractTest.class.getMethod(
"runBeforeAfters", (Class<?>[]) null);
FrameworkMethod f = new FrameworkMethod(m);
if (first != null && !first.equals(f)) {
afters.add(0, f);
}
} catch (NoSuchMethodException e) {
// Do nothing
}
}
}
base.evaluate();
succeeded(method);
} catch (Throwable t) {
failed(t, method);
throw t;
} finally {
finished(method);
}
}
};
}
/**
* @deprecated since 5.9.2, use
* {@link ScreenshotTaker#dumpPageSource(org.openqa.selenium.WebDriver, String)}
* instead.
*/
@Deprecated
public File dumpPageSource(String filename) {
ScreenshotTaker taker = new ScreenshotTaker();
return taker.dumpPageSource(driver, filename);
}
@Override
public void failed(Throwable e, FrameworkMethod method) {
String className = getTestClassName(method);
String methodName = method.getName();
log.error(String.format("Test '%s#%s' failed", className, methodName),
e);
if (lastScreenshot == null || lastPageSource == null) {
ScreenshotTaker taker = new ScreenshotTaker();
if (lastScreenshot == null) {
File temp = taker.takeScreenshot(driver, filePrefix);
lastScreenshot = temp != null ? temp.getAbsolutePath() : null;
}
if (lastPageSource == null) {
File temp = taker.dumpPageSource(driver, filePrefix);
lastPageSource = temp != null ? temp.getAbsolutePath() : null;
}
}
log.info(String.format("Created screenshot file named '%s'",
lastScreenshot));
log.info(String.format("Created page source file named '%s'",
lastPageSource));
super.failed(e, method);
}
@Override
public void finished(FrameworkMethod method) {
log.info(String.format("Finished test '%s#%s'",
getTestClassName(method), method.getName()));
lastScreenshot = null;
lastPageSource = null;
super.finished(method);
}
public RemoteWebDriver getDriver() {
return driver;
}
public String getServerURL() {
return serverURL;
}
protected String getTestClassName(FrameworkMethod method) {
return method.getMethod().getDeclaringClass().getName();
}
protected void logOnServer(String message) {
if (driver != null) {
driver.get(String.format(
"%s/restAPI/systemLog?token=dolog&level=WARN&message=----- WebDriver: %s",
serverURL, URIUtils.quoteURIPathComponent(message, true)));
} else {
log.warn(String.format("Cannot log on server message: %s", message));
}
}
public void runBeforeAfters() {
ScreenshotTaker taker = new ScreenshotTaker();
lastScreenshot = taker.takeScreenshot(driver, filePrefix).getAbsolutePath();
lastPageSource = taker.dumpPageSource(driver, filePrefix).getAbsolutePath();
}
public void setDriver(RemoteWebDriver driver) {
this.driver = driver;
}
public void setServerURL(String serverURL) {
this.serverURL = serverURL;
}
@Override
public void starting(FrameworkMethod method) {
String message = String.format("Starting test '%s#%s'",
getTestClassName(method), method.getName());
log.info(message);
String className = getTestClassName(method);
String methodName = method.getName();
filePrefix = String.format("screenshot-lastpage-%s-%s", className,
methodName);
logOnServer(message);
}
@Override
public void succeeded(FrameworkMethod method) {
if (lastPageSource != null) {
new File(lastPageSource).delete();
}
if (lastScreenshot != null) {
new File(lastScreenshot).delete();
}
}
/**
* @deprecated since 5.9.2, use
* {@link ScreenshotTaker#takeScreenshot(org.openqa.selenium.WebDriver, String)}
* instead.
*/
@Deprecated
public File takeScreenshot(String filename) {
ScreenshotTaker taker = new ScreenshotTaker();
return taker.takeScreenshot(driver, filename);
}
}