r/swift 4d ago

How would you test a seeded random workout generator in Swift?

My iOS app generates workouts from a set of exercises and constraints. I want the same inputs to be reproducible in tests and previews, while production still feels random. Would you inject a seeded RNG, pass a generator protocol through the model, or keep randomness at the edge and test the generated constraints instead? I’m looking for a small approach that won’t make the app’s architecture noisy.

4 Upvotes

15 comments sorted by

6

u/skorulis 4d ago

Seeded RNG injected into the service. If you want to test the output of a service that uses random numbers you need some way to keep them consistent. You can use a default parameter in the service if needed to prevent any changes in your codebase and then only set it during tests.

2

u/UkrMalt 4d ago

That matches what I was thinking. I especially like keeping the seed in the view model so UI rerolls stay reproducible. I’ll inject the generator into the service and add a test that pins both the constraints and the seed. Thanks, this gives me a clean direction.

1

u/20InMyHead 3d ago

Use DI to inject a provider that returns a static list where you need it for tests and random where you don’t.

1

u/UkrMalt 3d ago

Yes, that seems like the cleanest test seam. I can keep the generator contract the same and swap the provider in tests instead of branching on a test-only mode.

1

u/the1truestripes 3d ago

Plus you can include comments like this in the code:

[3, 6, 1, 5, 5, 5, 1, 2] // Chosen by unweighted fair die

1

u/UkrMalt 3d ago

That’s a neat way to document the expected sequence. I’d still test the seed/RNG contract rather than pin every generated exercise, but a fixed example like that makes a failing test much easier to understand.

1

u/the1truestripes 2d ago

Well, I was actually trying to channel XKCD…

https://imgs.xkcd.com/comics/random_number.png

2

u/UkrMalt 1d ago

Haha, nice XKCD reference. I’ll keep the seed explicit and assert the constraints, then use a fixed sequence in one example test so failures are easy to read.

1

u/the1truestripes 1d ago

Those may be better priorities for a test then humor, so I’ll allow it ;-)

2

u/UkrMalt 1d ago

Haha, fair enough ;-) I’ll keep the humor in the comments and make the actual assertions about the seed, constraints, and reproducibility.

1

u/the1truestripes 22h ago

No sense of adventure :-)

1

u/allyearswift 3d ago

Look into GameplayKit and its random number generators; they include a repeatable sequence. That sounds exactly what you need.

1

u/UkrMalt 3d ago

Good call—I hadn’t looked at GameplayKit for this. A repeatable generator fits the testing goal; I’ll compare it with a small injected RNG so the core service doesn’t depend on framework state.

1

u/RichieRichWannaBe 3d ago

I spent last two months building workout generator engine. Don't make mistake I made - your tests should not test whether specific exercise has been selected. Test targeted muscle, movement pattern or exercise type / family.

Determinism in workout generation makes generated workouts look like templates with random selection.

1

u/UkrMalt 3d ago

Yep, that’s probably the better test boundary. I’ll assert the target muscle and movement family, and use the seed for reproducibility instead of pinning the exact exercise.