Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to take screenshot at the point where test fail in Espresso?

I am looking for a way to take a screenshot of device after test failed and before get closed.

like image 800
think_better Avatar asked Jul 22 '16 06:07

think_better


People also ask

What is screenshot testing?

How does it work? screenshot-tests-for-android generates deterministic screenshots of views during a test run. By deterministic, we mean that every single run of your tests generates a pixel-perfect screenshot of the app as it would appear on a user's device.


2 Answers

Easiest way that I found:

@Rule
public TestRule watcher = new TestWatcher() {
  @Override
  protected void failed(Throwable e, Description description) {
    // Save to external storage (usually /sdcard/screenshots)
    File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
        + "/screenshots/" + getTargetContext().getPackageName());
    if (!path.exists()) {
      path.mkdirs();
    }

    // Take advantage of UiAutomator screenshot method
    UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    String filename = description.getClassName() + "-" + description.getMethodName() + ".png";
    device.takeScreenshot(new File(path, filename));
  }
};
like image 115
Kevin Brotcke Avatar answered Oct 25 '22 00:10

Kevin Brotcke


Another improvement to previous answers. I'm using the experimental Screenshot API

public class ScreenshotTestRule extends TestWatcher {

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

    takeScreenshot(description);
  }

  private void takeScreenshot(Description description) {
    String filename = description.getTestClass().getSimpleName() + "-" + description.getMethodName();

    ScreenCapture capture = Screenshot.capture();
    capture.setName(filename);
    capture.setFormat(CompressFormat.PNG);

    HashSet<ScreenCaptureProcessor> processors = new HashSet<>();
    processors.add(new CustomScreenCaptureProcessor());

    try {
      capture.process(processors);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

I've created CustomScreenCaptureProcessor because BasicScreenCaptureProcessor uses /sdcard/Pictures/ folder and I encountered IOExceptions on some devices when creating the folder/image. Please note that you need to place your processor in the same package

package android.support.test.runner.screenshot;

public class CustomScreenCaptureProcessor extends BasicScreenCaptureProcessor {    
  public CustomScreenCaptureProcessor() {
    super(
        new File(
            InstrumentationRegistry.getTargetContext().getExternalFilesDir(DIRECTORY_PICTURES),
            "espresso_screenshots"
        )
    );
  }
}

Then, in your base Espresso test class just add

@Rule
public ScreenshotTestRule screenshotTestRule = new ScreenshotTestRule();

If you wish to use some protected folder, this did the trick on an emulator, tho it didn't work on a physical device

@Rule
public RuleChain screenshotRule = RuleChain
      .outerRule(GrantPermissionRule.grant(permission.WRITE_EXTERNAL_STORAGE))
      .around(new ScreenshotTestRule());
like image 33
Maragues Avatar answered Oct 25 '22 00:10

Maragues