-
Notifications
You must be signed in to change notification settings - Fork 209
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
Add a surround() function. #377
Comments
I think this is something we should push on. Some open questions I have:
cc @jakemac53 @grouma for thoughts. cc @mehmetf for anything we should be thinking about in terms of solving the |
Yes, we would need this at the granularity of test for |
I believe the proposed API would already support that without a callback to |
@natebosch how does this feature interact with |
Yes, the question is whether you need to create a different closure for each callback. For example to capture a different
I don't think it would be used for those at all.
@mehmetf - one thing I'm curious about as we get further with this - there is not argument to the |
What happens if a user nests multiple calls to |
You can't and therefore you can't await in a setup function that runs in fakeAsync. The test callback needs to await/resolve futures. Either way, the behavior is surprising but for different reasons. Today, the surprise is due to setup functions running in real async zone. You can await in it but things break down if the future you created is not resolved by the time test callback executes. This creates subtle bugs. With Other issues to consider:
These solutions are not ideal :( The best solution is either supporting fake_async in dart testing explicitly or disallowing setup/teardown functions completely in widget tests. The latter is what Ian had proposed but it is an enormous breaking change that will make a lot of people upset. |
I worry that breaking all async
How often does that happen given that we strongly encourage awaiting all futures? Do you have an example of a bug where a Future was not awaited in |
I worry that you are right. There does not seem to be a good solution to this. Either way, the user is restricted and needs to understand some nuance between fake and real async zones. I will put together a concrete use case and we can examine. Given how difficult this road has been and the fact that the solution will create other problems, I am inclined to look at that case and see what else we can do. Perhaps lints? documentation? I even wonder if a language level change might help here. Perhaps we could tag certain Futures so that if they are awaited in a different zone than they were created, we throw a runtime error instead of hanging... |
I looked at a couple of use cases that necessitated running setUp/tearDown functions in fake async zone. In either case, the problem is that we are using some framework that is relying on an asynchronous operation but is not giving the user a way to await for the said operation directly. Rather, it relies on callbacks which often gets buried under several Given that our efforts so far did not yield a desirable design, I am OK simply pushing frameworks to expose such operations as PS: There are other use cases for |
cc @lrhn for thoughts. This API could make it easier to test with zone overridden values for the redesign of |
It would bring us one step close to proper aspect oriented programming 👍 It's not technically necessary, you can always define your own: surround(
void Function() Function(void Function()) surround,
void Function(void Function(String, void Function()) test) callback) {
callback((msg, body) => test(msg, surround(body));
}
/// and then
surround((body) {
runZoned(body, zoneSpecification : ...);
}, (test) {
test("test1", () {
// runs in zone
});
test("test2", () {
// also runs in zone.
});
} It doesn't solve the issue of running multiple tests in the same zone, but keeping tests as separate as possible is probably a good idea anyway. We could also make void group(String name, void Function() tests, {void Function() wrap(void Function()? test)} { ... } and then each (I'd probably want the same for tear-down and set-up, but then I never liked the current approach where you declare shared variables and set them up and tear them down repeatedly. It makes it impossible to run async tests concurrently (but then again, single threaded execution is so much easier to reason about, so it's probably better for the average user. Still, it would be safer to have |
Another potential use case: cc @polina-c - would you be interested in an API where you could configure the leak tracker wrapping at the |
Given Dart's Zone-based asynchrony, there are a number of use-cases for being able to wrap entire tests—including the setup and teardown—in a single zone (see for example this thread). A straightforward way to accomplish this would be to provide a
void surround(Future callback(Future runTest()))
function that defines a callback to run around the test and any inner setups or teardowns. For example:There are a lot of edge-cases that would need to be worked out, and it's possible that one of them will make this not work. But it's something to keep in mind.
The text was updated successfully, but these errors were encountered: