-
Notifications
You must be signed in to change notification settings - Fork 23
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
Leak Tracker should avoid flagging non-leaks in Flutter tests #239
Comments
Thanks for opening this discussion and thus creating opportunity to discuss the concerns (not uncommon) in details. I would like to add couple clarifications. resets the widget tree for every test, there shouldn't be any need at all to call dispose() within the test. Method 'dispose' cleans up allocated resources. Some of them may not relate to widget tree. For example, native memory, allocated for images. Such resources are not released after reset of the widget tree. It relates to the nature of the method 'dispose'. The rule is 'call dispose every time, because it is incapsulated and responsibility of the method The bottom line is: even if in this concrete case the method 'dispose' is doing nothing, invoke it, because next versions of involved libraries may change the situation. any disposable which is declared within a test() or testWidgets() method, should be safe from memory leaks Leak tracker for tests does not track anything that is created 'outside' of callback of
How does it sound? |
You provided some example code, but that looks like hypothetical code. If the Leak Tracker has identified actual leaks from disposables that are declared within tests, can you please show one of those real examples? |
Sure! This leak of curved animation was caught by a test: |
Ok, for the conversation record, the curved animation leak bug was located in a framework file, not a test. The leak corresponded to a Therefore, the Can you please show a real leak that was found and fixed in which the leak itself was attached to a variable that was instantiated within a test? Please see my I've asserted that it should be impossible to create a leak when instantiating a disposable within a test and then not disposing of it. We're looking for a counter-example to that assertion. |
Thanks. Example of real memory leak: In addition, the method dispose can be buggy, that means it can forget to dispose some disposable members, created during lifecycle. And this should be caught by leak tracker. It will not be, if we opt out these instances. I do not have concrete examples for such cases, but they are possible and this suggest to just dispose the instances instead of (1) creating and maintaining special logic to opt them out and (2) instructing what is ok to not dispose, because it will violate contracted area of concern for the client of the disposable. How does it sound? |
Are they though? If there isn't a single such example in the framework's test suite, and if this leak tracker hasn't found a single such concrete example within test code, then maybe it's not possible. In fact, my original point was exactly that. Or if they are possible, it requires a substantially different scenario from what the leak tracker is complaining about in tests.
This brings us right back to where we started. You're suggesting a blanket policy for all test writing in Flutter as a safeguard for a problem that still doesn't have a single example, and a problem which may actually be impossible due to how the test runner resets the widget tree between tests. Unless I've missed something, we're still lacking any motivating example for why this leak tracker should impose a policy on all tests that will ever be written. I also haven't seen how the mis-information associated with that policy will be mitigated. If you truly cannot find a single concrete example to inform this rule, I would encourage you to adjust the approach. |
Possible example: instance of Image. It reserves native resources. |
Can you please show the code? If there's no code then there's no example. I'd like to see an actual memory leak from within a test method by way of a disposable that's created in the test, just as I indicated in the OP. |
Sorry for not structuring my answers well. “Unknowing developers will read these teardowns, assume that they're necessary, and draw incorrect conclusions about how the Flutter test runner works.” "If there's no code then there's no example. " Let me add structure to the discussion. There are two types of leaks in testing: prod and test-only. I agree that: Should we stop caring about test-only leaks at all? This is example of issue, caught by leak tracker, where not disposed test-only disposable caused broken test isolation: flutter/flutter#149288 It is very hard to catch if the test isolation is broken. That’s why we have randomization for testing. And there is agreement in the team that test isolation is important. Can leak tracker detect test-only not disposed and opt out from leak tracking? Thank you for bringing this concern and for pushing me to structure this. |
The Leak Tracker currently identifies non-leaks as leaks in Flutter tests for disposable objects.
The following is an example of such a false-positive:
The Leak Tracker says that we should explicitly call
dispose()
onfocusNode
to avoid a leak. However, because the Flutter test runner resets the widget tree for every test, there shouldn't be any need at all to calldispose()
within the test. There's no leak.This same situation applies to things like
ScrollController
,TextEditingController
, etc.What to do about it
Option 1: Do nothing
The first option is to do nothing. The Leak Tracker will identify situations like the one above as leaks, and developers working on the Flutter framework will be forced to add a teardown for every such object, which calls
dispose()
.Pro's:
Con's:
Option 2: Don't identify these as leaks
The second option is to adjust the Leak Tracker so that it doesn't identify non-leaking disposable within tests as leaks.
The pro's and con's here are the inverse of those listed above.
How to avoid false positives in tests
In the general case, any disposable which is declared within a
test()
ortestWidgets()
method, should be safe from memory leaks. When that test ends, the declaration scope is gone, and the widget tree has also been released by the test runner. Therefore, GC is free to collect the disposable, without explicitly calling dispose.Regex could probably be used to achieve this filtering:
testWidgets()
or outside. If it's inside, then throw away that leak candidate because it isn't a leak. If it's outside oftestWidgets()
then it might be a legitimate leak, report it.The text was updated successfully, but these errors were encountered: