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].
} |
dnfield
left a comment
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
In that case, do we need to fail if !acquired?
There was a problem hiding this comment.
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.
It’s recursive, so it will keep waiting.
There was a problem hiding this comment.
Ahh I get it now. Ok.
Will the test just timeout if they failed to convert to imageview first?
9f96994 to
87b53eb
Compare
|
@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 aFutureof 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.