Open iamdefinitelyahuman opened 4 years ago
setup_first
is a bad name for explaining what it does. How about create_snapshot
?
Also, injecting the fixtures is pretty magical. Is it all the fixtures that are available, or only the ones I pull in via my test case where I initialized it?
It's magical, but it's the same magic that we're used to dealing with via pytest. In my mind it moves the structure closer to that of writing a normal test.
It would have to be limited to the fixtures that were requested in the test case... I don't think I'm able to grab a fixture outside of the local namespace of the test.
I don't think I'm able to grab a fixture outside of the local namespace of the test.
How do you think pytest knows about fixtures in the first place?
Per gitter convo: maybe do away with the need to have a test_stateful
at all, and instead use a class decorator to indicate a state machine. The fixtures can be given as input args to the decorator:
@state_machine(Depositor, accounts)
class NewStateMachine:
setup_first
is a bad name for explaining what it does. How aboutcreate_snapshot
?
I thought setup_first
to mirror the teardown
and teardown_final
methods (which maybe should be included in the example).
Perhaps...
initial_setup
setup
teardown
final_teardown
What about:
create_snapshot
setup_case
teardown_case
revert_snapshot
Pros:
snapshot
s (happens once) vs. case
s (happens N
times)Related - it should be possible to selectively disable coverage analysis during a stateful test. Either on a per rule/invariant basis, or a broad "disable during invariants".
Also related - add support for @precondition
: https://hypothesis.readthedocs.io/en/latest/stateful.html#preconditions
Not sure where this fits in with the given syntax, it might still make the most sense as a decorator.
Would also be useful to allow a rule to have a "weight", i.e. making a specific rule twice as likely to run as the others.
Or a sort-of hybrid invariant/rule that executes after every rule but prior to the invariants
I was just looking at this: https://hypothesis.readthedocs.io/en/latest/stateful.html#hypothesis.stateful.consumes
~It should be possible to use strategies within the setup_case
method.~
It should be possible to create a type of initialize
rule that accepts strategies and always executes, always prior to any rules. This should be seperate from setup_case
- an unhandled exception during setup_case
indicates a failure in the state machine itself.
The ability to feature strategies based on state of a StateMachine:
class StateMachine:
st_account = strategy("accounts")
st_amount = strategy("uint256", stateful_exclude=lambda val, self: val < self.token.totalSupply())
...
def rule_mint(self, a="st_account", val="st_amount"):
self.token.mint(a, val)
def rule_transfer(self, a1="st_account", a2="st_account", val="st_amount"):
self.token.transfer(a2, val, {"from": a1})
Allow printing something only when an invariant is violated (maybe some StateMachine.display
function that executes when a falsifying example is found for each step along the way)
Stumbled on this issue by reading hypothesis docs and finding precondition
and thinking it would be nifty to have that in brownie. Right now, I am hardcoding the conditions when the rule is allowed to fire in the body of the rule of the function, which must be wrong. I imagine @precondition
in hypothesis is used to better guide the rule firing.
Overview
Improve the design of Brownie state machines.
This is a work in progress, if you have any ideas feel free to leave them as comments or reach out on Gitter.
Specification
__init__
method. Handling this as a classmethod is confusing and unintuitive. Replace it with an optionalsetup_first
classmethod that achieves the same functionality (runs once prior to the snapshot).state_machine
fixture to a decorator which accepts pytest fixtures to be made available in the test.Example
This is a condensed version of the example state machine given in the documentation:
Here is the same state machine, rewritten with the proposed new functionality:
Dependencies
Breaking change. Can happen as a part of
v2.0.0
. Also, this means plenty of time to bikeshed about the design :smile: