Development

Taking A Screenshot When A JUnit Test Fails

When writing automated tests for Swing, AWT or any other UI component, 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.

package net.time4tea;
 
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
 
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class TakingAScreenshotOnFailureRule implements MethodRule {
 
    private final File directory;
 
    public TakingAScreenshotOnFailureRule(File directory) {
        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), "png");
                    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, String format) {
        try {
            saveScreenshotTo(file, format);
        } catch ( Exception e ) {
            System.err.println("Can't save screenshot to " + file + ", " + e);
        }
    }
 
    private static BufferedImage takeScreenshot() throws AWTException {
        Robot robot = new Robot();
        Rectangle captureSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
        return robot.createScreenCapture(captureSize);
    }
 
    private static void saveScreenshotTo(File file, String format) throws AWTException, IOException {
        ImageIO.write(takeScreenshot(), format, file);
    }
}
comments powered by Disqus