Yes, I now think that's the right choice.
This is starting to dovetail with other conversations I've been having about timeouts, and how inappropriate they are. Especially in the environment of Swift Testing's parallel test runner.
Essentially, Swift Testing's test runner aims to minimize total test runtime, but it doesn't so much care about how long each individual test takes. Moreover, you can't really guarantee "consistent" test execution time with parallel runtime - some tests will run on the E core, some will run on the P core. System load is a thing. So many other variables to take into account.
In practice, this means that using a timeout is not the right approach: they'll work if you have only a handful of tests (or you only run a handful at a time), but once you scale up, then your tests will start becoming flakier and flakier.
As an example, this pitch initially specified a default timeout of 1 second. However, when I implemented this and ran the entire test swift testing test suite, it flaked because #expect(until: .passesOnce) { true }
would consistently take >2 seconds to run. However, sometimes the test was still reported as passing, even though the test runtime was >2 seconds. Which is based entirely on whether the timeout task ran first, or the expression-running task ran first. I then changed the default timeout to a minute, and only earlier today did I realize that timeouts are fundamentally unworkable: There will be very large test suites where even a minute will be too short for a trivial #expect(until: .passesOnce) { true }
.
I chatted with @grynspan about this earlier, something he suggested is ignoring wall clock times and specifying the number of times to run the expression. Which would basically turn the implementation into a for loop. That's workable, reliable, and easy to implement. But I'm worried that it's going to be difficult for test authors to predict good "number of times to run" values - running a fast expression a million times can happen on the order of milliseconds. Additionally, this drops the ability to cancel the polling if the expression being polled doesn't return quickly enough - though, that is much less of a concern when we have parallel test execution.
I've only come to this conclusion today, I don't have further thoughts on how to decide when to stop polling.
That's where I'm at: timeouts are easy for humans to think & reason about, but are inappropriate for the parallel nature of Swift Testing's test runner. The other idea I've seen is very hard for a human to predict. At this point, I think figuring out the mechanism used to decide when to stop polling is more important than the default value for how "long" that mechanism should run for - or if there should even be a default.