Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Screenshot via Test Listener integration
Browse files Browse the repository at this point in the history
If derived from FunctionalTest, tests will generate screen shots
in the event of before & after click, navigating to a new url, or
test exception.
  • Loading branch information
djansen-redhat authored and Patrick Huang committed Dec 13, 2013
1 parent 42454c1 commit d93e8ed
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 20 deletions.
62 changes: 44 additions & 18 deletions functional-test/src/main/java/org/zanata/page/WebDriverFactory.java
Expand Up @@ -22,6 +22,7 @@

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;
Expand All @@ -30,13 +31,16 @@
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.service.DriverService;
import org.openqa.selenium.support.events.EventFiringWebDriver;
import org.zanata.util.PropertiesHolder;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.zanata.util.TestEventListener;

import static org.zanata.util.Constants.chrome;
import static org.zanata.util.Constants.firefox;
Expand All @@ -49,6 +53,7 @@ public enum WebDriverFactory {

private WebDriver driver;
private DriverService driverService;
private TestEventListener eventListener;

public WebDriver getDriver() {
if (driver == null) {
Expand All @@ -71,6 +76,22 @@ public String getHostUrl() {
return PropertiesHolder.getProperty(zanataInstance.value());
}

private WebDriver enableScreenshots(WebDriver webDriver) {
log.info("Enabling screenshot module...");
webDriver = new Augmenter().augment(webDriver);
String screensDir = System.getProperty("webdriver.screenshot.dir");
eventListener = new TestEventListener(webDriver, screensDir);
return new EventFiringWebDriver(webDriver).register(eventListener);
}

public void updateListenerTestName(String testname) {
try {
eventListener.updateTestID(testname);
} catch (NullPointerException npe) {
System.out.print("Driver not yet set");
}
}

private WebDriver createDriver() {
String driverType =
PropertiesHolder.getProperty(webDriverType.value(), "htmlUnit");
Expand All @@ -88,30 +109,35 @@ private WebDriver configureHtmlDriver() {
}

private WebDriver configureChromeDriver() {
driverService =
new ChromeDriverService.Builder()
.usingDriverExecutable(
new File(PropertiesHolder.properties
.getProperty("webdriver.chrome.driver")))
.usingAnyFreePort()
.withEnvironment(
ImmutableMap
.of("DISPLAY",
PropertiesHolder.properties
.getProperty("webdriver.display")))
.withLogFile(
new File(PropertiesHolder.properties
.getProperty("webdriver.log"))).build();
driverService = new ChromeDriverService.Builder()
.usingDriverExecutable(
new File(PropertiesHolder.properties
.getProperty("webdriver.chrome.driver")))
.usingAnyFreePort()
.withEnvironment(ImmutableMap.of("DISPLAY",
PropertiesHolder.properties
.getProperty("webdriver.display")))
.withLogFile(
new File(PropertiesHolder.properties
.getProperty("webdriver.log"))).build();
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities
.setCapability("chrome.binary", PropertiesHolder.properties
.getProperty("webdriver.chrome.bin"));
capabilities.setCapability("chrome.binary", PropertiesHolder.properties
.getProperty("webdriver.chrome.bin"));
capabilities.setCapability("chrome.switches", Arrays
.asList("--start-maximized"));
try {
driverService.start();
} catch (IOException e) {
throw new RuntimeException("fail to start chrome driver service");
}
return new RemoteWebDriver(driverService.getUrl(), capabilities);

WebDriver webDriver =
new RemoteWebDriver(driverService.getUrl(), capabilities);
if (System.getProperty("webdriver.screenshot.dir")
!= null) {
webDriver = enableScreenshots(webDriver);
}
return webDriver;
}

private WebDriver configureFirefoxDriver() {
Expand Down
160 changes: 160 additions & 0 deletions functional-test/src/main/java/org/zanata/util/TestEventListener.java
@@ -0,0 +1,160 @@
package org.zanata.util;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.events.WebDriverEventListener;

/**
* @author Damian Jansen <a
* href="mailto:djansen@redhat.com">djansen@redhat.com</a>
*/
@Slf4j
public class TestEventListener implements WebDriverEventListener {

private WebDriver driver;
private String targetDir;
private String testId = "";

/**
* A registered TestEventListener will perform actions on navigate,
* click and exception events
* @param drv the WebDriver to derive screen shots from
* @param targetDirectory full path to screen shot storage
*/
public TestEventListener(WebDriver drv, String targetDirectory) {
driver = drv;
targetDir =
targetDirectory.endsWith("/") ? targetDirectory
: targetDirectory.concat("/");
log.info("Writing screenshots to {}", targetDir);
}

/**
* Update the screen shot directory/filename test ID component
* @param testId test identifier string
*/
public void updateTestID(String testId) {
this.testId = testId;
}

private void createScreenshot(String ofType) {
String outputDir;
try {
outputDir = targetDir.concat(testId);
File testIDDir = new File(outputDir);
testIDDir.mkdirs();
File screenshotFile =
((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(outputDir
+ File.separator + generateFileName(ofType)));

} catch (WebDriverException wde) {
throw new RuntimeException("[Screenshot]: Invalid WebDriver: "
+ wde.getMessage());
} catch (IOException ioe) {
throw new RuntimeException("[Screenshot]: Failed to write to "
+ targetDir);
} catch (NullPointerException npe) {
throw new RuntimeException("[Screenshot]: Null Object: "
+ npe.getMessage());
}
}

private String generateFileName(String ofType) {
return testId.concat(":").concat(String.valueOf(new Date().getTime()))
.concat(ofType).concat(".png");
}

private boolean isAlertPresent(WebDriver driver) {
try {
driver.switchTo().alert();
return true;
} catch (NoAlertPresentException nape) {
return false;
}
}

@Override
public void afterNavigateTo(String url, WebDriver driver) {
createScreenshot("_nav");
}

@Override
public void beforeClickOn(WebElement element, WebDriver driver) {
createScreenshot("_preclick");
}

@Override
public void afterClickOn(WebElement element, WebDriver driver) {
if (isAlertPresent(driver)) {
log.info("[Screenshot]: Prevented by Alert");
return;
}
createScreenshot("_click");
}

@Override
public void onException(Throwable throwable, WebDriver driver) {
createScreenshot("_exc");
}

/*
* Unused interface functions
*/
@Override
public void afterChangeValueOf(WebElement element, WebDriver driver) {
}

@Override
public void beforeNavigateTo(String url, WebDriver driver) {
}

@Override
public void beforeNavigateBack(WebDriver driver) {
}

@Override
public void afterNavigateBack(WebDriver driver) {
}

@Override
public void beforeNavigateForward(WebDriver driver) {
}

@Override
public void afterNavigateForward(WebDriver driver) {
}

@Override
public void beforeFindBy(By by, WebElement element, WebDriver driver) {
}

@Override
public void afterFindBy(By by, WebElement element, WebDriver driver) {
}

@Override
public void beforeChangeValueOf(WebElement element, WebDriver driver) {
}

@Override
public void beforeScript(String script, WebDriver driver) {
}

@Override
public void afterScript(String script, WebDriver driver) {
}

}
@@ -0,0 +1,65 @@
/*
* Copyright 2013, Red Hat, Inc. and individual contributors as indicated by the
* @author tags. See the copyright.txt file 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.zanata.feature;

import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;
import org.zanata.page.WebDriverFactory;
import org.zanata.page.utility.HomePage;
import org.zanata.util.ResetDatabaseRule;
import org.zanata.workflow.AbstractWebWorkFlow;

import java.util.Date;

/**
* @author Damian Jansen <a
* href="mailto:djansen@redhat.com">djansen@redhat.com</a>
*/
@Slf4j
@Category(DetailedTest.class)
public class FunctionalTest {

@ClassRule
public static ResetDatabaseRule resetDatabaseRule = new ResetDatabaseRule();

@Rule
public TestName name = new TestName();

@Before
public void setupTestFunction() {
WebDriverFactory.INSTANCE.getDriver();
updateTestId();
String date = new Date().toString();
log.info("[TEST] {}:{}:{}", getClass().getName(), name.getMethodName(), date);
}

private void updateTestId() {
String testId = getClass().getName();
testId = testId.substring(testId.lastIndexOf(".")+1)
.concat(":").concat(name.getMethodName());
WebDriverFactory.INSTANCE.updateListenerTestName(testId);
}
}
Expand Up @@ -27,6 +27,7 @@
import org.junit.experimental.categories.Category;
import org.zanata.feature.BasicAcceptanceTest;
import org.zanata.feature.DetailedTest;
import org.zanata.feature.FunctionalTest;
import org.zanata.page.account.ChangePasswordPage;
import org.zanata.page.account.MyAccountPage;
import org.zanata.page.utility.DashboardPage;
Expand All @@ -42,7 +43,9 @@
* href="mailto:djansen@redhat.com">djansen@redhat.com</a>
*/
@Category(DetailedTest.class)
public class ChangePasswordTest {
public class ChangePasswordTest extends FunctionalTest {

// Override database class rule
@Rule
public AddUsersRule addUsersRule = new AddUsersRule();

Expand Down
Expand Up @@ -28,6 +28,7 @@
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.zanata.feature.DetailedTest;
import org.zanata.feature.FunctionalTest;
import org.zanata.page.account.RegisterPage;
import org.zanata.workflow.BasicWorkFlow;

Expand Down
Expand Up @@ -28,6 +28,7 @@
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.zanata.feature.DetailedTest;
import org.zanata.feature.FunctionalTest;
import org.zanata.page.account.RegisterPage;
import org.zanata.util.rfc2822.ValidEmailAddressRFC2822;
import org.zanata.workflow.BasicWorkFlow;
Expand Down
Expand Up @@ -28,6 +28,7 @@
import org.junit.experimental.categories.Category;
import org.zanata.feature.BasicAcceptanceTest;
import org.zanata.feature.DetailedTest;
import org.zanata.feature.FunctionalTest;
import org.zanata.page.projects.ProjectSourceDocumentsPage;
import org.zanata.util.CleanDocumentStorageRule;
import org.zanata.util.PropertiesHolder;
Expand All @@ -47,7 +48,9 @@
* href="mailto:djansen@redhat.com">djansen@redhat.com</a>
*/
@Category(DetailedTest.class)
public class UploadTest {
public class UploadTest extends FunctionalTest {

// Override database rule for data
@Rule
public SampleProjectRule sampleProjectRule = new SampleProjectRule();

Expand Down

0 comments on commit d93e8ed

Please sign in to comment.