Capturing screenshots of the browser via Selenium is fairly easy to achieve (see a sample method here), but triggering a screenshot only when a test fails is useful for both debugging and result reporting, however this requires a little more code and some modifications to your tests.
JUnit5
For Junit5, add the following class file into your test project:
package com.example;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Optional;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
/**
*
* @author steve
*
* to use, add the following to your JUnit5 tests:
*
* @RegisterExtension
* ScreenshotWatcher5 watcher = new ScreenshotWatcher5(driver, "target/surefire-reports");
*
*/
public class ScreenshotWatcher5 implements TestWatcher {
WebDriver driver;
String path;
public ScreenshotWatcher5(WebDriver driver, String path) {
this.driver = driver;
this.path = path;
}
@Override
public void testAborted(ExtensionContext context, Throwable throwable) {
// do something
}
@Override
public void testDisabled(ExtensionContext context, Optional<String> optional) {
// do something
}
@Override
public void testFailed(ExtensionContext context, Throwable throwable) {
// do something
captureScreenshot(driver, context.getDisplayName());
}
@Override
public void testSuccessful(ExtensionContext extensionContext) {
// do something
}
public void captureScreenshot(WebDriver driver, String fileName) {
try {
new File(path).mkdirs();
try ( FileOutputStream out = new FileOutputStream(path + File.separator + "screenshot-" + fileName + ".png")) {
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
}
} catch (IOException | WebDriverException e) {
System.out.println("screenshot failed:" + e.getMessage());
}
}
}
And the add the following to the tests themselves:
@RegisterExtension
ScreenshotWatcher5 watcher = new ScreenshotWatcher5(driver, "target/surefire-reports");
On failure, this will generate a file named after the failed test, in the designated relative path.
JUnit4
For JUnit4, add the following class file into your test project:
package com.example;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.openqa.selenium.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author steve
*
* to use, add the following to your JUnit4 tests:
*
* @Rule
* public ScreenshotRule4 rule = new ScreenshotRule4(driver, "target/surefire-reports");
*
*/
public class ScreenshotRule4 implements MethodRule {
WebDriver driver;
String path;
public ScreenshotRule4(WebDriver driver, String path) {
this.driver = driver;
this.path = path;
}
@Override
public Statement apply(final Statement statement, final FrameworkMethod method, Object target) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
} catch (Throwable throwable) {
captureScreenshot(driver, method.getName());
throw throwable;
}
}
public void captureScreenshot(WebDriver driver, String fileName) {
try {
new File(path).mkdirs();
try ( FileOutputStream out = new FileOutputStream(path + File.separator + "screenshot-" + fileName + ".png")) {
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
}
} catch (IOException | WebDriverException e) {
System.out.println("screenshot failed:" + e.getMessage());
}
}
};
}
}
And the add the following to the tests themselves:
@Rule
public ScreenshotRule4 rule = new ScreenshotRule4(driver, "target/surefire-reports");
On failure, this will generate a file named after the failed test, in the designated relative path.
TestNG
For TestNG, add the following class file into your test project:
package com.example;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
/**
*
* @author steve
*
* to use, add the following to your TestNG tests:
*
* @AfterTest
* public void tearDown(ITestResult result) {
* if (!result.isSuccess()) {
* Screenshot.capture(driver, "target/surefire-reports", result.getName());
* }
* }
*
*
*/
public class Screenshot {
static WebDriver driver;
public static final void capture(WebDriver driver, String path, String fileName) {
try {
new File(path).mkdirs();
try ( FileOutputStream out = new FileOutputStream(path + File.separator + "screenshot-" + fileName + ".png")) {
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
}
} catch (IOException | WebDriverException e) {
System.out.println("screenshot failed:" + e.getMessage());
}
}
}
And the add the following to the tests themselves:
@AfterMethod
public void tearDown(ITestResult result) {
if (!result.isSuccess()) {
Screenshot.capture(driver, "target/surefire-reports", result.getName());
}
}
On failure, this will generate a file named after the failed test, in the designated relative path.