-
-
Notifications
You must be signed in to change notification settings - Fork 483
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
Scoped / Thread safe verion of Randomizer.Seed = new Random(SEED); #100
Comments
Hi @oliverkane , This is a good idea. We could probably have
I think it should be possible but will take some refactoring. I'll try to take a look later today. |
That's pretty much a dream for me, since that means that you can chain a global seed to "child" seeds by var masterFaker = new Faker().Seed(12345);
var childFaker1 = new Faker().Seed(masterFaker.Random.Number(Int32.MaxValue);
var childFaker2 = new Faker().Seed(masterFaker.Random.Number(Int32.MaxValue);
var childFaker3 = new Faker().Seed(masterFaker.Random.Number(Int32.MaxValue); Which would allow for pretty complex, but still deterministic results in even the most complex of situations. Should even work across app boundaries that way too. Your response warms my heart, because I was digging around the source considering making a fork, but I'm waaay out of my depth. |
Hey @oliverkane , Just a quick update on this. I was able to get pretty far on this tonight only 7 failing tests out of 251. Not too bad... The only hold up are these static Bogus/Source/Bogus/Randomizer.cs Lines 588 to 636 in 1a28328
All these I need a bit more time to think and chew on the overall architecture here. The Rest assured, I still think your idea of setting isolated seed values on Also, if you (or anyone on the watchlist) have suggestions, I'd love to hear alternate points of views on the subject and any suggestions on design/architectural patterns would be cool. Just going to jot down some random ideas that are floating in my head:
It's 3AM and need to get some sleep. Good night 💤 🛌 :) |
To respond to bullet points before I start my day:
I'll have more when I have some weekend time. |
Hey @oliverkane , Good news! I was able to arrive at a decent implementation of this. The solution, I think is two part: 1) flowing the randomizer/localized seed across the entire internal dependency graph and 2) having a
[Fact]
public void clone_has_different_rules()
{
var rootFaker = new Faker<Examples.Order>()
.UseSeed(88)
.RuleFor(o => o.OrderId, f => f.IndexVariable++)
.RuleFor(o => o.Quantity, f => f.Random.Number(1, 3))
.RuleFor(o => o.Item, f => f.Commerce.Product());
var cloneFaker = rootFaker.Clone()
.RuleFor(o => o.Quantity, f => f.Random.Number(4, 6));
var rootOrder = rootFaker.Generate();
var clonedOrder = cloneFaker.Generate();
rootOrder.Quantity.Should()
.BeGreaterOrEqualTo(1).And
.BeLessOrEqualTo(3);
clonedOrder.Quantity.Should()
.BeGreaterOrEqualTo(4).And
.BeLessOrEqualTo(6);
} And for the grand finale, parallel determinism with [Fact]
public void parallel_determinism()
{
var orderFaker = new Faker<Examples.Order>()
.RuleFor(o => o.OrderId, f => f.IndexVariable++)
.RuleFor(o => o.Quantity, f => f.Random.Number(1, 3))
.RuleFor(o => o.Item, f => f.Commerce.Product());
var orders = ParallelEnumerable.Range(1, 5)
.Select(threadId =>
orderFaker
.Clone()
.UseSeed(88)
.Generate(4).ToArray()
).ToArray();
foreach( var arrayOf4 in orders )
{
CheckSequence(arrayOf4);
}
}
private void CheckSequence(Examples.Order[] items)
{
items.Select(i => i.Item)
.Should().Equal("Tuna", "Pants", "Shoes", "Soap");
items.Select(i => i.Quantity)
.Should().Equal(3, 1, 3, 2);
} The relevant tests are in This is pretty badass if you ask me. 🎸 😎 And way fun to implement too. Pretty happy about it and I think it feels just about right in terms of maintenance. I don't think I'm willing to go much more beyond this tho since this does really push Bogus right to the edge of the API "getting too complex" imho; although deprecating the "global seed" would bring it back in line a bit, but would also break a lot of code out in the wild. We'll leave that one static I'll clean up the implementation tomorrow and probably merge bit later this weekend. Need some finishing touches on the API and need to break out some classes into their own files. But the meat of it looks pretty good. 🍖 5AM..! Yeow. Time flies when you haven' fun! Time for sleep! 💤 🛌 💼 👔 "Taking care of business every day... Taking care of business every way..." EDIT |
Are there plans to add the UseSeed(...) method to the generic Faker too? (Bogus.Faker, not Bogus.Faker) EDIT: Example usage:
|
Hi there. I saw that there's a static property which can be used for deterministic results.
However, if I use this approach with multiple threads, I get inconsistent results because my threads are asyncronous. Is there a method that I'm overlooking which would allow me a locally scoped version of this property? I'd very much like to be able to have 100+ concurrent operations going on and still get the benefit of determinism.
Thanks for your time! Love the library either way 👍
The text was updated successfully, but these errors were encountered: