-
Notifications
You must be signed in to change notification settings - Fork 26.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Android e2e screenshot #84472
Android e2e screenshot #84472
Conversation
a419690
to
75e1536
Compare
@blasten Please correct me if I'm wrong, I think you mean for the API to be used like so: final myApp = find.byType(MyApp);
final bytes = binding.deviceScreenshot(myApp);
await expectLater(bytes, matchesGoldenFile('screenshot.png')); This will work internally. I'm wondering if it would make sense to contain the screenshotting logic within the matcher, for consistency with the same API as // [matchesDeviceScreenshotGoldenFile] provided by `package:integration_test`
await expectLater(myApp, deviceScreenshotMatchesGoldenFile('screenshot.png')); |
82714b8
to
0c7fb03
Compare
There would be two different ways to get bytes out of the device. External usersExternal users will use A comparator can be added to the file under integrationDriver(onScreenshot: (List<int> png) {
/* do something with it. Like saving to disk or sending them to Skia Gold. */
}); Internal usersSince the internal infra already knows how to reach the service for image comparison. There won't be need for final bytes = binding.deviceScreenshot(myApp);
await expectLater(bytes, anyComparator('screenshot.png')); Any thoughts? |
(for external users) Is there a mechanism for users to identify which screenshot is received? Or are users expected to maintain the ordering between the I think this works, but it's also worth noting that this approach to use the driver script may be a stopgap solution in the meantime. Since #66264, users can run integration tests with (For the internal example) Did you mean to use final bytes = binding.takeScreenshot('myApp');
await expectLater(bytes, matchesGoldenFile('screenshot.png')); The string parameter to Future<List<int>> takeScreenshot(Finder finder) {
// Take screenshot of the dimensions bound by [finder].
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My major concern is over synchronization. Right now, as implemented, at least two frames will get pumped after requesting a screenshot, but maybe more.
How will test authors know they're getting the frame they really care about, particularly when native UI might be involved and still animating/loading?
/** | ||
* Captures a screenshot by drawing the view to a Canvas. | ||
* | ||
* <p>It also converts {@link FlutterView} to an image view, since {@link FlutterSurfaceView} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has some pretty serious performance implications right?
IOW, doing this is incompatible with using integration_test for performance testing.
Is there some other way of doing this without impacting global test state for the rest of the test execution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the answer seems to be yes. Why would we have this fallback though? Why not just fail if instrumentation is unavailable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed offline: we should probably make this part of the integration_test API so developers can opt into this if they want. If they ahven't opted in, we should fail if instrumentation isn't available.
waitForAndroidFrame( | ||
() -> { | ||
waitForAndroidFrame( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to mean that we'll pump at least two frames after calling this method, right?
How will this be stable for screenshot tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For image views: Thsi should work because we'll know we've had at least one frame drawn by flutter.
For instrumentation tests: This should work because the Dart part of the test should have gotten us to a stable non-animating point in the application, and now should be waiting before tapping or doing anything else.
@blasten - will the new method block if awaited until the screenshot is finished?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed support for instrumentation tests until #56591 is addressed.
It rasterizes in a separate background thread, so it doesn't block the main thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, do we need to fail if !acquired
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still seems to be an issue - I'm not sure if I'm just missing somethign here, but it seems like if acquired
is false we'll fail to produce a screenshot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s recursive, so it will keep waiting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh I get it now. Ok.
Will the test just timeout if they failed to convert to imageview first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right
@dnfield PTAL |
Gold has detected about 4 new digest(s) on patchset 36. |
Gold has detected about 4 new digest(s) on patchset 37. |
Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change). If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
Implement Android view screenshot in integration_tests.
This PR adds support for the existing
takeScreenshot(String name)
method on Android.List of changes:
takeScreenshot(String name)
return type is now aFuture
of the byte array. This works with the existing dependencies in g3. Example:The byte array is also sent to the host via the driver script where it can be sent to services like Skia Gold for pixel comparisons. Here's an example:
test_driver/integration_test.dart:
binding.convertFlutterSurfaceToImage()
as suggested by @dnfield. This is required prior to callingtakeScreenshot()
.Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.