Skip to content
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

Merged
merged 6 commits into from Jun 24, 2020

Conversation

christian-muertz
Copy link
Contributor

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.

@codecov-commenter
Copy link

codecov-commenter commented May 25, 2020

Codecov Report

Merging #48 into master will decrease coverage by 3.71%.
The diff coverage is 56.25%.

Impacted file tree graph

@@            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     
Impacted Files Coverage Δ
packages/golden_toolkit/lib/src/configuration.dart 83.33% <ø> (ø)
...es/golden_toolkit/lib/src/multi_screen_golden.dart 100.00% <ø> (ø)
packages/golden_toolkit/lib/src/testing_tools.dart 90.27% <56.25%> (-9.73%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 80f9d57...cd40278. Read the comment docs.

@christian-muertz
Copy link
Contributor Author

We should probably add sth like a AssetPrimeStrategy to make this change backwards compatible.

@coreysprague
Copy link
Contributor

@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.

@christian-muertz
Copy link
Contributor Author

I know in our projects we have some other asset related widgets that we may need to await as well

Can you make an example?

@coreysprague
Copy link
Contributor

@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?

@christian-muertz
Copy link
Contributor Author

@coreysprague please let me know what you think about this implementation. Is a PrimeAssets type the right way to go? Its a bit ugly because it takes in so many arguments, but otherwise we cannot call matchesGoldenFile without that info.

/// See also:
/// * [GoldenToolkitConfiguration.primeAssets] to configure a global asset prime function.
Future<void> defaultPrimeAssets(WidgetTester tester, String name, Finder finder) =>
matchesGoldenFile(name).matchAsync(finder);
Copy link
Contributor

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 😄

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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 {
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% agree.

Copy link
Contributor

@coreysprague coreysprague left a 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!

@christian-muertz
Copy link
Contributor Author

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.

I am confused where to put such a test. Shouldn't there sth. like screen_golden_test.dart. This would imply moving the screenMatchesGolden to be moved to sth. like screen_golden.dart

@christian-muertz
Copy link
Contributor Author

Or at least a testing_tools_test.dart

@coreysprague
Copy link
Contributor

@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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// a custom implementation.
/// a custom implementation. This implementation will be removed in a future release.

@coreysprague
Copy link
Contributor

@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.

@coreysprague
Copy link
Contributor

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.

@christian-muertz
Copy link
Contributor Author

@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.

Sure. Make sure to precache DecoratedBoxes as well

@coreysprague coreysprague changed the base branch from master to image-loading June 24, 2020 15:35
@coreysprague coreysprague merged commit d66b52d into eBay:image-loading Jun 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

screenMatchesGolden sometimes creates failure folders even when the test succeeds
3 participants