-
Notifications
You must be signed in to change notification settings - Fork 588
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
Allow customization of step runner in run_state_machine_as_test #1709
Comments
I think async stateful testing is harder than you think 😨. This code doesn't really work... try:
if print_steps:
self.print_start()
await self.check_invariants()
while should_continue.more():
value = data.draw(self.steps())
if print_steps:
self.print_step(value)
await self.execute_step(value)
await self.check_invariants()
finally:
if print_steps:
self.print_end()
await self.teardown()
self._nursery.cancel_scope.cancel() ...because the order in which functions execute is really important and Hypothesis can't control or even see it. Trio randomises task order on it's event loop, which is fine. Unfortunately it also uses an independent (to clarify: Hypothesis can't shrink or even reliably report non-deterministic bugs, because they tend to be so flaky, and that includes everything on top of the non-deterministic scheduler) So we have two potential solutions, which might end up as two distinct
|
I would also remove |
I think it would be problematic for Trio to use the global Alternatively: |
I think the general problem of "the Trio scheduler is non-deterministic, but we want deterministic or at least reproducible tests" should probably be solved in
Nope, each call to Long-term, trio may well adopt a deterministic scheduling policy so I'd rather not over-engineer anything right now 😉. Truly deterministic tests also require that the completion order of concurrent operations (hence tasks available to schedule) be deterministic too. However I'm happy to leave controlling IO delays and faults for another day! |
Oh, we're both right. There's a global Random object (used to give the system clock a random offset), and a per-
But if you're not using hypothesis, then you should use the random scheduling, because it's a kind of poor-man's-hypothesis, to make sure your code doesn't depend on scheduling order :-). If the randomness affects your tests then that means you have a bug, and a non-deterministic failure is better than a deterministic pass that hides the bug until it's too late. Of course when you're using hypothesis that's different: you still want random scheduling order, it's just that you want the randomness to be under hypothesis's control. (And ideally with a custom strategy that picks "weird" schedules to flush out bugs, but we can ignore that for now.) |
Agreed! You usually need a pretty good trace or replay capability to understand and fix this kind of bug, but Trio is about as good for that as you can get 😄
Concretely then, would you be happy with a PR against Trio to make the scheduler use the global Note that this would make the scheduler deterministic so that Hypothesis can minimise examples which exhibit observable scheduler-related behaviour, at the cost of hiding the relatively rare scheduling-related bugs that would only be exposed by a different seed. |
BTW what we do in hypothesis core which would also work here is to create new |
An argument to
This still perturbs the global PRNG though, so if someone has some script where they use |
Alright, I think there's two parts to this issue: First, how the Trio scheduler can be made deterministic for Hypothesis: #1714 and python-trio/pytest-trio#73 between them manage it.
Second, I think So under my proposal there's not much more to be done in upstream Hypothesis - though I remain happy to help with integrations on the Trio end too 😄 |
Hi,
Release 3.84 broke hypothesis-trio (it used to monkey patch
StateMachineRunner.run
, butStateMachineRunner
is gone now)This is needed because we must start a trio loop to run the
TrioGenericStateMachine
(given itexecute_step
,check_invariants
andteardown
methods are asynchronous)I think we could clean this hack by having
run_state_machine_as_test
checking if the given state machine contains a custom step runner:What do you think ? 😃
The text was updated successfully, but these errors were encountered: