Espresso: How to take a screenshot when a test fails

11 February 2021 stoefln Leave a comment Uncategorized

Ever wondered how to make debugging of tests easier by taking a screenshot right when a test fails? This is what the JUnit TestWatcher can be used for.

public class ScreenshotTestRule extends TestWatcher {

  protected void failed(Throwable e, Description description) {
    super.failed(e, description);

    String filename = description.getTestClass().getSimpleName() + "-" + description.getMethodName();

    ScreenCapture capture = Screenshot.capture();

    HashSet processors = new HashSet<>();
    processors.add(new BasicScreenCaptureProcessor());

    try {
    } catch (IOException e) {

Configuring the storage location for the screenshot

BasicScreenCaptureProcessor uses /sdcard/Pictures/ folder and this can lead to IOExceptions on some devices when trying to save the screenshot.

You might get an error similar to this: The directory /storage/emulated/0/Pictures/screenshots does not exist and could not be created or is not writable.

That’s why we override the basic functionality and configure another directory:


public class CustomScreenCaptureProcessor extends BasicScreenCaptureProcessor {    
  public CustomScreenCaptureProcessor() {
        new File(
            InstrumentationRegistry.getTargetContext().getExternalFilesDir(DIRECTORY_PICTURES), "test_run_screenshots"

Be aware that needs to be placed in the same directory as your Of cause, you need to make use of it inside your TestWatcher class:

Instead of

processors.add(new BasicScreenCaptureProcessor());


processors.add(new CustomScreenCaptureProcessor());

Timing of taking the screenshot

If you use the rule, as I outlined above, it might take the screenshot too late. For example, your activity might crash and all you get is a screenshot of the home screen.

There is a RuleChain that allows you to get the timing right. This is the code without the RuleChain:

public final ActivityTestRule _activityRule = new ActivityTestRule<>(MainActivity.class);

public ScreenshotTestWatcher _screenshotWatcher = new ScreenshotTestWatcher();

And this is the code with a RuleChain, to make sure that the screenshot is taken BEFORE the activity is destroyed:

private final ActivityTestRule _activityRule = new ActivityTestRule<>(MainActivity.class);

public final TestRule activityAndScreenshotRule = RuleChain
        .around(new ScreenshotTestWatcher());

Moving the screenshots to the test automation host:

Probably you want to send the screenshots via email, slack or make them available via a webserver. To do that you can use Android Debug Bridge (ADB):

Simply call adb pull to copy the files over to your host system:

adb pull "/storage/sdcard0/DCIM/test_run_screenshots"


Tags: ,

Like this article? there’s more where that came from.