Thanks for the tips. Here's what I ended up doing:
@pytest.mark.usefixtures('dummy_profiles')
def test_level_obj_bought(fake_user: User, fake_profile: GameProfile,
random_profileset: ProfileSet):
factories = sampled_from(random_profileset.factories)
ovens = sampled_from(random_profileset.ovens)
uids = text(min_size=8, max_size=8, alphabet=string.ascii_uppercase + string.digits)
class LevelObjectBoughtMachine(RuleBasedStateMachine):
def __init__(self, fake_user: User, fake_profile):
super().__init__()
self.fake_user = fake_user
self.fake_profile = fake_profile
# Clear stuff
@rule(factory=factories, uid=uids)
def test_factory_bought(self, factory: Factory, uid: str):
# apply events
@rule()
@precondition(lambda self: self.fake_user.savegame.restaurant.levelObjects)
def test_unique_uids(self):
# assert properties
factory = partial(LevelObjectBoughtMachine, fake_user, fake_profile)
factory.__name__ = LevelObjectBoughtMachine.__name__
run_state_machine_as_test(factory, settings(max_examples=1000))
So I'm defining the rule machine inside the function. I'm actually totally ok with this, since it means I can use strategies that depend on my fixtures. Technically I don't even need the partial thing there (or to pass stuff to __init__), I can just access the fixtures from the test function scope. In fact that might even be better since it hammers home the fact these are global, mutable things we're using.
Interestingly Hypothesis needs the __name__ of the factory, for its database I'm guessing?
Anyway, maybe this pattern should be documented somewhere? Feels useful. Thanks for the help.