package com.softwaremill.common.test.web.selenium;
import com.google.common.base.Charsets;
import com.thoughtworks.selenium.Selenium;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.server.RemoteControlConfiguration;
import org.openqa.selenium.server.SeleniumServer;
import org.testng.Assert;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Listeners;
import com.softwaremill.common.test.web.selenium.screenshots.FailureTestListener;
import com.softwaremill.common.test.web.selenium.screenshots.Screenshotter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author maciek
*/
@Listeners({FailureTestListener.class})
public abstract class AbstractSeleniumTest {
private static SeleniumServer server;
public static Selenium selenium;
private static SeleniumBrowserProperties browserProperties;
private static String seleniumHost;
private static int seleniumServerPort;
private static boolean debug;
private static int seleniumTimeout;
static {
seleniumHost = System.getProperty("selenium.server", "127.0.0.1");
seleniumServerPort = Integer.parseInt(System.getProperty("selenium.server.port", "14444"));
String testServerPort = System.getProperty("selenium.testserver.port", "8280");
String testServerUrl = System.getProperty("selenium.testserver.url", "http://localhost");
String browserCommand = System.getProperty("selenium.browser.command", "*firefox");
debug = Boolean.parseBoolean(System.getProperty("selenium.debug.enabled", "true"));
seleniumTimeout = Integer.parseInt(System.getProperty("selenium.timeout", "120"));
browserProperties = new SeleniumBrowserProperties(browserCommand, testServerUrl, testServerPort);
}
public AbstractSeleniumTest() {
}
/**
* Returns object with properties for the browser started by selenium, including base url.
* This can be used to modify this properties, e.g. when using different test url.
*/
public SeleniumBrowserProperties getBrowserProperties() {
return browserProperties;
}
@BeforeSuite
public void setupSelenium() throws Exception {
System.out.println("--- Starting selenium server with debug set to " + debug);
RemoteControlConfiguration rcc = new RemoteControlConfiguration();
rcc.setTimeoutInSeconds(seleniumTimeout);
rcc.setPort(seleniumServerPort);
//rcc.setMultiWindow(true);
rcc.setSingleWindow(false);
PrintStream ps = System.out; // backup
System.setOut(new PrintStream(new FileOutputStream("logfile"), false, Charsets.UTF_8.name()));
rcc.setDebugMode(debug);
server = new SeleniumServer(false, rcc);
System.setOut(ps); // restore
server.start();
System.out.println("--- Started selenium server");
}
@AfterSuite(alwaysRun = true)
public void stopSelenium() throws Exception {
System.out.println("--- Stopping selenium server");
server.stop();
System.out.println("--- Stopped selenium server");
}
@BeforeTest
public void setupBrowser() throws Exception {
String url = browserProperties.getBrowserURL();
if (browserProperties.getBrowserPort() != null) {
url += ":" + browserProperties.getBrowserPort();
}
System.out.println("--- Starting browser on url: " + url);
selenium = new SMLSelenium(
seleniumHost,
seleniumServerPort,
browserProperties.getBrowserCommand(),
url,
new Screenshotter() {
@Override
public void doScreenshot() {
try {
// make a screenshot
captureScreenshot();
} catch (Exception e) {
// shouldn't happen
throw new RuntimeException(e);
}
}
});
selenium.start();
System.out.println("--- Started browser");
// perform optional logic
afterSeleniumStart();
}
@AfterTest
public void stopBrowser() throws Exception {
beforeSeleniumStop();
System.out.println("--- Stopping browser");
selenium.stop();
System.out.println("--- Stopped browser");
}
/**
* @deprecated Please use regular TestNG asserts
*
* @param var
* @throws Exception
*/
@Deprecated
public static void assertTrue(boolean var) throws Exception {
if (!var) {
captureScreenshot();
}
Assert.assertTrue(var);
}
/**
* @deprecated Please use regular TestNG asserts
*
* @param o1
* @param o2
* @throws Exception
*/
@Deprecated
public static void assertEquals(Object o1, Object o2) throws Exception {
if (!o1.equals(o2)) {
captureScreenshot();
}
Assert.assertEquals(o1, o2);
}
/**
* @deprecated Please use regular TestNG asserts
*
* @param message
* @throws Exception
*/
@Deprecated
public static void fail(String message) throws Exception {
captureScreenshot();
Assert.fail(message);
}
/**
* Use {@link #captureScreenshot(String)} instead.
*/
@Deprecated
public static File captureScreenshot() throws Exception {
return captureScreenshot("");
}
public static File captureScreenshot(String testName) throws Exception {
File f = createTempArtifactFile("selenium_screenshot_", testName, ".png");
selenium.captureEntirePageScreenshot(f.getAbsolutePath(), "");
publishArtifact(f);
return f;
}
public static File captureHtmlSource(String testName) throws Exception {
File f = createTempArtifactFile("selenium_source_", testName, ".txt");
String htmlSource = selenium.getHtmlSource();
FileUtils.write(f, htmlSource);
publishArtifact(f);
return f;
}
private static void publishArtifact(File f) {
System.out.println("##teamcity[publishArtifacts '" + f.getAbsolutePath() + "']");
}
private static File createTempArtifactFile(String prefix, String testName, String suffix)
throws IOException {
String date = new SimpleDateFormat(".yyyy-MM-dd-HH-mm-ss.").format(new Date());
return File.createTempFile(prefix + testName + "_", date + "failed" + suffix);
}
protected void afterSeleniumStart() throws Exception {
// base implementation does nothing
}
protected void beforeSeleniumStop() throws Exception {
// base implementation does nothing
}
@Deprecated // Use SeleniumCommands.clickAndWait instead
public static void clickAndWait(String locator, String timeout) {
SeleniumCommands.clickAndWait(locator, timeout);
}
}