@caiozullo Thanks for sharing another workaround! It's interesting that your version passes with 100,000 iterations, but I think your code ultimately has the same flaw as the code I originally posted.
You start a new task to send the notification like this:
Task {
NotificationCenter.default.post(
name: UIApplication.userDidTakeScreenshotNotification, object: nil
)
}
And in doing so you are giving other parts of the code just a little bit of time to execute their work, in particular it seems enough time has passed for the for await
in the view model to start. So while it seems to work in this case, there are no guarantees that doing work in a new task will give some other unrelated async code enough time to do its work.
In the end I don't really think firing up this new task is much different from the Task.yield()
from my original code sample.
Spinning up a new task seems to have a higher success rate, but so does changing my code to call Task.yield()
twice. When two Task.yield()
s are added to my original example then it also passes with 100,000 iterations:
await Task.yield()
await Task.yield()
NotificationCenter.default.post(
name: UIApplication.userDidTakeScreenshotNotification, object: nil
)
Test Suite 'ScreenshotWatcherTests.xctest' passed at 2022-05-16 08:37:05.310.
Executed 100000 tests, with 0 failures (0 unexpected) in 61.353 (97.453) seconds
So this all takes us back to the original reason I posted. There just doesn't seem to be a way to write a test for async code like this and guarantee it will pass. We are either getting very lucky, or if the system was under enough stress I think the view model task could fail to progress to the for await
before the notification is posted, and thus fail.
All of this is to say that it seems the only way for us to guarantee the order of execution of these things is if we can somehow serialize the execution of tasks. At @Philippe_Hausler's request I am going to start a new forum post on just that topic if anyone is interested in following along. I'll post a link here when I do.