android-testify icon indicating copy to clipboard operation
android-testify copied to clipboard

Screens which inflate views at a later time are never captured

Open DanielJette opened this issue 3 years ago • 3 comments

Describe the bug Regardless of which capture method I try, I can never actually capture anything on screen which either inflates views after creation or adds views to a recyclerview. Using Screenshot.capture() as a fourth capture method would fix this. Screenshot.capture() gives you access to a bitmap so comparing shouldn't been an issue.

This issue relates to:

  • [x] The Kotlin library
  • [ ] The Gradle plugin
  • [ ] The IntelliJ Platform plugin
  • [ ] The sample code
  • [ ] The documentation

To Reproduce Try to screenshot any activity with just a recyclerview into which you add views after onCreate of the  Activity.

Expected behavior Screenshot is correctly taken.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: MacOS

Target Android Device (please complete the following information):

  • Device: Pixel
  • Physical or Virtual: Android Virtual Device (Emulator)
  • API Level: 28
  • Testify Key: [e.g. Output from ./gradlew testifyKey]

Additional context Add any other context about the problem here.


Copied from @videogreg93 https://github.com/Shopify/android-testify/issues/245

DanielJette avatar Aug 05 '22 23:08 DanielJette

Hi @videogreg93 thanks for the bug report Testify will capture the screen immediately after the screen goes idle as it assumes that, once the UI thread is idle, that all rendering is completed.

In order to allow for dynamic content to be loaded later, Testify will internally synchronize with the Espresso onIdle() method. In a scenario such as you've described, I would recommend you define an Espresso idling resource which you can use to signal to Testify that you've completed loading your content.

DanielJette avatar Aug 05 '22 23:08 DanielJette

Copied from https://github.com/Shopify/android-testify/issues/245#issuecomment-925922709

Hey there, thanks for tip! I tried adding a simple idling resource which just waits a couple of seconds to see if that would work, but even then while the screen is clearly finished rendering, this is the resulting screenshot. blank Hard to say exactly what's going on, the only thing I know is that using Screenshot.capture() correctly captures the view, while these methods do not.

DanielJette avatar Aug 05 '22 23:08 DanielJette

@videogreg93 I was thinking about this problem a little more last night and I'm wondering if you might be running in to a GPU-acceleration problem. Testify's default capture method is not capable of capturing SurfaceViews, such as Google MapView or Jetpack Compose elements. Some other graphical elements such as elevation/shadows are also not captured since they're not present in the Bitmap buffer of the Activity, but rather contained in hard-accelerated surfaces. This means that the default Testify capture methods are not able to "see" that content. In order to capture SurfaceView contents, you will need to use an alternative capture method that is capable of capturing SurfaceViews.

I would recommend you try enabling PixelCopyCapture:

import com.shopify.testify.TestifyFeatures.PixelCopyCapture

@ScreenshotInstrumentation
@Test
fun default() {
    rule
        .withExperimentalFeatureEnabled(PixelCopyCapture)
        .assertSame()
}

PixelCopy grabs the content directly from the GPU on your device, so it's quite sensitive to hardware differences. As such, I recommend you also enable a lower exactness threshold for the matching using setExactness().

import com.shopify.testify.TestifyFeatures.PixelCopyCapture

@ScreenshotInstrumentation
@Test
fun default() {
    rule
        .withExperimentalFeatureEnabled(PixelCopyCapture)
        .setExactness(0.9f)
        .assertSame()
}

You can find an example of this here

It's possible that this capture method will work for your tests.

DanielJette avatar Aug 05 '22 23:08 DanielJette