Development

Taking A Screenshot When A WebDriver Test Fails

When writing automated tests for using WebDriver, especially when running those tests on a remote machine, when a test fails it can be very useful to capture the screen/component that was showing at the end of the test.

Here we use a JUnit Rule, introduced in JUnit 4, to capture the screen at the end of the test.

Note that this code assumes your WebDriver can take a screen-shot, which isn’t true of all implementations…

package net.time4tea;
 
import com.google.common.io.Files;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import java.io.File;
import java.io.IOException;
 
public class TakingAWebDriverScreenshotOnFailureRule implements MethodRule {
 
    private final WebDriver driver;
    private final File directory;
 
    public TakingAWebDriverScreenshotOnFailureRule(WebDriver driver, File directory) {
        this.driver = driver;
        this.directory = directory;
        directory.mkdirs();
    }
 
    @Override
    public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    base.evaluate();
                } catch (Throwable throwable) {
                    silentlySaveScreenshotTo(filenameFor(method));
                    throw throwable;
                }
            }
        };
    }
 
    private File filenameFor(FrameworkMethod method) {
        String className = method.getMethod().getDeclaringClass().getName();
        String methodName = method.getName();
 
        return new File(directory, className + "_" + methodName + ".png");
    }
 
    private void silentlySaveScreenshotTo(File file) {
        try {
            saveScreenshotTo(file);
        } catch ( Exception e ) {
            System.err.println("Can't save screenshot to " + file + ", " + e);
        }
    }
 
    private  void saveScreenshotTo(File file) throws IOException {
        byte[] bytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
        Files.write(bytes, file);
    }
}
comments powered by Disqus