From 7e6c095d96ddaac97a7af2813e87700fc1d70379 Mon Sep 17 00:00:00 2001 From: Michael Hoisie Date: Wed, 24 Jan 2024 12:39:37 -0800 Subject: [PATCH] Treat exceptions during DefaultFailureHandler screenshots as suppressed exceptions If an Espresso failure occurs, DefaultFailureHandler will capture a window snapshot and take a screenshot. However, if a RuntimeException occurs during this process, it will replace the original exception. An example is if there is an exception that occurs during a View's rendering logic. The original exception will trigger DefaultFailureHandle's screenshot, which may trigger a different exception, hiding the root cause. PiperOrigin-RevId: 601202589 --- espresso/CHANGELOG.md | 1 + .../test/espresso/base/DefaultFailureHandler.java | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/espresso/CHANGELOG.md b/espresso/CHANGELOG.md index 72b3b0f70..db122b358 100644 --- a/espresso/CHANGELOG.md +++ b/espresso/CHANGELOG.md @@ -22,6 +22,7 @@ The following artifacts were released: * Remove Kotlin StringKt calls from Java code * Remove all support for Android SDKs < 19. Minimum is API 19 (Android Kit Kat 4.4) * Stop posting empty tasks to background threads when running in non-remote mode +* Better handle exceptions that may occur in DefaultFailureHandler's hierarchy capture and screenshot process. **New Features** diff --git a/espresso/core/java/androidx/test/espresso/base/DefaultFailureHandler.java b/espresso/core/java/androidx/test/espresso/base/DefaultFailureHandler.java index 785b54f2e..b33751f96 100644 --- a/espresso/core/java/androidx/test/espresso/base/DefaultFailureHandler.java +++ b/espresso/core/java/androidx/test/espresso/base/DefaultFailureHandler.java @@ -119,8 +119,14 @@ static Truncater getAmbiguousViewMatcherException @Override public void handle(Throwable error, Matcher viewMatcher) { int count = failureCount.incrementAndGet(); - TestOutputEmitter.captureWindowHierarchy("explore-window-hierarchy-" + count + ".xml"); - takeScreenshot("view-op-error-" + count); + try { + TestOutputEmitter.captureWindowHierarchy("explore-window-hierarchy-" + count + ".xml"); + takeScreenshot("view-op-error-" + count); + } catch (RuntimeException screenshotException) { + // Ensure that the root cause exception is surfaced, not an auxiliary exception that may occur + // during the capture/screenshot process. + error.addSuppressed(screenshotException); + } // Iterates through the list of handlers to handle the exception, but at most one handler will // update the exception and throw at the end of the handling.