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
WIP: Find all Image widgets and precache them before comparing #48
WIP: Find all Image widgets and precache them before comparing #48
Conversation
Codecov Report
@@ Coverage Diff @@
## master #48 +/- ##
==========================================
- Coverage 99.41% 95.69% -3.72%
==========================================
Files 7 7
Lines 172 186 +14
==========================================
+ Hits 171 178 +7
- Misses 1 8 +7
Continue to review full report at Codecov.
|
We should probably add sth like a AssetPrimeStrategy to make this change backwards compatible. |
@christian-muertz thanks for submitting this! I suspect we will want to allow this be configurable and extensible. I know in our projects we have some other asset related widgets that we may need to await as well. We could consider making this opt-in behavior for backwards compatibility for now. I think the global "config" concept I referenced in your other PR would be applicable for allowing this control without breaking existing consumers. That being said, I'm really happy you started on this. It's been on my list for awhile. |
Can you make an example? |
@christian-muertz -- I believe there are some examples of images being used outside of Image widgets. For example, as part of BoxDecorations. That being said, I think the way we should approach this is to start with this being an opt-in change. We can plan to make it a breaking change in a future release by deprecating the legacy implementation. That way we can have a few releases to solicit feedback and identify if there are other cases that this package should support out of the box. I think it might make sense to implement this opt-in with the configuration mechanism I introduced in the linked PR. Would you be willing to make that change? |
e75e0de
to
3487dad
Compare
ca1060b
to
2dbfa24
Compare
@coreysprague please let me know what you think about this implementation. Is a |
/// See also: | ||
/// * [GoldenToolkitConfiguration.primeAssets] to configure a global asset prime function. | ||
Future<void> defaultPrimeAssets(WidgetTester tester, String name, Finder finder) => | ||
matchesGoldenFile(name).matchAsync(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.
so I think we can simplify the prime assets api...
this old version was such a hack, that I don't think the filename OR the finder actually matter...
I believe we can remove them from the signature, and just hardcode the filename to a constant, and the finder to be the root of the widget tree. That might make the signature more palatable 😄
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.
and just hardcode the filename to a constant
This would result in a file always being created. I will investigate why this hack works and implement sth. similar that does not need a fileName and thus does not create a file.
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.
Ok the legacy version does not work for huge images. Seems like calling mathcesGoldenFile only triggers the decompression and decoding of all images. For small images this may work because they finish decoding before the actual call but for bigger images this does not work reliable. @coreysprague Do you think a test that verifies that the new implementation works even for huge images would be useful? This would probably add another 5mb to the repo.
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.
Ok now I realized that matchesGoldenFIle just consumes some time which is enough for all the small images to be decoded. I ran a benchmark and matchesGoldenFile took an average of 25ms. Waiting for the same duration has the same effect... The time spent in the matchesGoldenFile
call should be relative to the time needed to load small images. I suggest just calling the heavy operations done by the function to waste some time in the legacy implementation.
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.
Waiting for a const Duration should be very flaky because we dont know the speed of the device the test is running on.
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.
Just commited legacyPrimeAssets
which just wastes time by rasterizing the next RepaintBoundary and converting the result image to a png.
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.
@christian-muertz you are correct. The old one triggered rasterization and essentially just wasted cycles, and generally worked, but not all the time.
I'm not too worried about the large image test for the new solution. The new solution is not dependent on winning a non-deterministic race. I think your proposal for an alternate legacy solution makes sense to me. This legacy implementation should be short lived anyway. I mostly just want to give consumers a release or two to migrate in case there are issues with the new solution.
expect(globalPrimeCalledCount, 1); | ||
}); | ||
|
||
testGoldens('screenMatchesGolden method level primeAssets trumps global configuration', (tester) async { |
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.
do you think we still need the method level override?
I can't decide. It would simplify the APIs if we stuck to the global override. With the way flutter test's test_config construct works, it can be set for particular sub-folders, or someone could alter it for just a file (or for a particular test by configuring before and reverting after).
what do you think?
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.
Then probably sth like configuration.copyWith
would be helpful
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.
100% agree.
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.
Left some comments. Mostly minor.
We should probably have a test that asserts a golden with an image using your new implementation, that will get the coverage back up, and ensure the behavior is working as expected.
Thanks again!
I am confused where to put such a test. Shouldn't there sth. like |
Or at least a |
@christian-muertz the test organization is a mess. It evolved very organically and has become unwieldy. For now, you can put it wherever. I think I'll try to find some time to re-organize the tests and make them more clear. |
Future<void> _primeImages(String fileName, Finder finder) => matchesGoldenFile(fileName).matchAsync(finder); | ||
/// A function that primes all assets by just wasting time and hoping that it is enough for all assets to | ||
/// finish loading. Doing so is not recommended and very flaky. Consider switching to [waitForAllImages] or | ||
/// a custom implementation. |
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.
/// a custom implementation. | |
/// a custom implementation. This implementation will be removed in a future release. |
@christian-muertz are you okay if I merge this into a branch and finish up the final pieces of feedback and deal with the merge conflicts? I'd like to get this feature included in the next release. |
Also, after thinking about it more, I think your initial instinct was correct. We should make the new image strategy the default behavior. I can provide instructions for how to use the legacy behavior in the release notes. |
Sure. Make sure to precache DecoratedBoxes as well |
Instead of calling
matchesGoldenFile
twice to prime all images, find all Image widgets and precache them so they are available instantly afterwards.I am not sure if this is enough because their could probably be other assets that are not images which are not loaded this way.