Skip to content

Conversation

@chunhtai
Copy link
Contributor

@chunhtai chunhtai commented Apr 17, 2019

Description

Make assets available during tests. This PR add a step to build asset bundle during test setup.
The test will load the bundle and mock the message channel to bypass the engine.

Related Issues

#12999

Tests

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (Please read Handling breaking changes). Replace this with a link to the e-mail where you asked for input on this proposed change.
  • No, this is not a breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change will leave behind a folder 'test_assets' in root directory.

Copy link
Contributor

Choose a reason for hiding this comment

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

Lets put this under build

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but it is not necessary to have build folder when running test, should I just create the build folder here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like test already write something into build. fixed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will run at the beginning of every test. I make it so it will only mock the first time it is called, after that will be no op

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be better to move this into the binding initialization code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@chunhtai
Copy link
Contributor Author

This will potential be a breaking change. If developer also mocking the message channel in their code. It might cause unexpected behavior during the test. Not sure if we need to care about this

Copy link
Contributor

Choose a reason for hiding this comment

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

Use fs.path

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to happen after the pub check, so that any assets from package dependencies will already exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated this function. Previously, it only mock when the first time it is called, and no op at later call.
That will pose an issue when some of our tests also mock the message channel for some specific test cases.

I updated it so it will mock or override existing mock every time it is called. To ensure the performance, I implement _ensureInitialized method to do the expansive operation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are these always strings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should be. will you suggest using Set?

Copy link
Contributor

Choose a reason for hiding this comment

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

Set<String> would be preferable to dynamic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

We should call this something other than mock. mockFlutterAssets?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, since all fields are static I would remove the class entirely and place them under the test bindings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@goderbauer goderbauer added framework flutter/packages/flutter repository. See also f: labels. tool Affects the "flutter" command-line tool. See also t: labels. labels Apr 17, 2019
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this add measurable overhead when running the test over and over again? If so, we could potentially reuse the existing pubGet check, make it return a bool for whether or not the pubspec.yaml file had updated. Only if the pubspec file is updated, or if the asset directory doesn't exist, do we need to re-run ot

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will only run once within a flutter test. The overhead is depends on the assets size.
I check the code in flutter run. the run cold will build it everytime, while run hot will check if the pubspec.yaml change or not. I think it is ok to always rebuild during test. if we want to be smart, we not only need to check the pubspec.yaml, we also need to check ant of assets files changed or not.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, thinking about it more - we can't really do this, since a user may edit an asset which would then not be copied.

We should expose a flag in the test command to disable this functionality though

Copy link
Contributor Author

Choose a reason for hiding this comment

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

you mean expose a flag to skip rebuilding asset?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, similar to how we have a --pub,--no-pub flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use the setMethodCallHandler method, then it wouldn't be a breaking change as the mocks would still take precedence.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I understand correctly, settMockMessageHandler is setting _mockHandlers, which is used for outgoing message. setMethodCallHandler is setting _handlers, which is for in coming message. The assets request is outgoing message. I think setting the _handlers will not be able to intercept the request?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh good point, my bad!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a flag.
Two thing concerns me here.

  1. Should we build the assets by default?
    2, When no-assets, should we still try to see if there is test assets built in previous test and use it if it exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My current implementation is yes for both

Copy link
Contributor

Choose a reason for hiding this comment

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

my two general concerns:

  1. Test startup speed - does building the asset bundle slow it down measurably? Try time flutter test <<something_test.dart>> in the gallery and compare.
  2. Users that are already mocking assets. Maybe --no-assets should also not set the env variable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't see too much difference. maybe 1 or 2 seconds slower out of 2mins. But I do want to point out one thing. The existing test that involve assets load are currently passed because of our fake async. The assets load never finished without my fix. Otherwise they will all fail. This might add some more running time

Copy link
Contributor

Choose a reason for hiding this comment

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

I would name this something more specific like --no-test-assets.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@jonahwilliams
Copy link
Contributor

Also, if you're concerned about rolling this out, you can always default it to off. though you'll want to make sure it is used by the gallery tests

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

LGTM

I have no other concerns from a tooling perspective. This implementation leaves us some room to optimize later if we need to, without breaking any users.

@chunhtai
Copy link
Contributor Author

@jonahwilliams I will like to enable the assets load by default since it is more intuitive to have the functionality enabled.

After think a little bit more, this should not be a breaking change, either. We should be good to merge this pr

@chunhtai chunhtai merged commit b275e11 into flutter:master Apr 18, 2019
@Hixie
Copy link
Contributor

Hixie commented Apr 23, 2019

This hurt test performance (see e.g. flutter_test_performance with_coverage_time_ms).
Filed #31511

@gadfly361
Copy link

@chunhtai Did this PR cover flutter drive or is it just for making assets available to flutter test? If just for flutter test is there planned support forflutter drive coming?

@chunhtai
Copy link
Contributor Author

chunhtai commented Apr 26, 2019

this is only for flutter test. I believe flutter drive is using the really device and assets is already available? @jonahwilliams

@jonahwilliams
Copy link
Contributor

@gadfly361 flutter drive runs your real application - assets are already loaded

@gadfly361
Copy link

@jonahwilliams @chunhtai Thank you for the quick reply!

@leishuai
Copy link

leishuai commented Jul 8, 2019

@jonahwilliams @chunhtai Thank you for the quick reply!

I found flutter drive can't load assets when running.

@chunhtai
Copy link
Contributor Author

chunhtai commented Jul 8, 2019

@jonahwilliams @chunhtai Thank you for the quick reply!

I found flutter drive can't load assets when running.

Hi @leishuai
Can you provide a reproducible code that can demonstrate the issue you are facing? In theory, the asset should be able to load without problem since driver test have the real message channel.

@leishuai
Copy link

leishuai commented Jul 9, 2019

@chunhtai
If I try with a simple demo app, it works. But in my app, there are lots of plugin and startup works in native(swift/kotlin) side. So I really don't know why it doesn't work. I also found other people complained about these downside.

@chunhtai
Copy link
Contributor Author

chunhtai commented Jul 9, 2019

@leishuai Let's continue our discussion in here #35720

@MisterJimson
Copy link

FYI this PR seems to have caused #35907

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

framework flutter/packages/flutter repository. See also f: labels. tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants