Skip to content
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

Provide some kind of "Retrieve" or "Sample" method, which returns one of the objects *already* built by a builder #37

Open
Quantumplation opened this issue May 21, 2015 · 4 comments

Comments

@Quantumplation
Copy link
Contributor

This may be out of the scope of how you're using the library, but one of the most common cases that we had to end up working around at work is telling the builder to use an existing object: for example, you want to create a bunch of classes, and then distribute them among a bunch of professors or the like.

It's not enough to simply use builders for the property, as then there would be no overlap: every course would get a distinct instructor, and often subtle bugs in testing only arise when there is this kind of overlap.

The solution we've been using is to generate a list of instructors, and then for each course that gets built, pick a random element from this list. This is a relatively tiny bit of boilerplate, but it gets annoying when you're doing it in many different tests.

I want to add a "Sample" or "Retrieve" or "Past" method to a builder (naming things is hard, ok?) which can accomplish this with no boilerplate, and give code that looks like below:

var instructors = Builder<Instructor>.CreateListOfSize(10).All().WithTenure();
var courses = Builder<Course>.CreateListOfSize(100)
                             .All().Set(x => x.Instructor, () => instructors.Sample());

This is close to perfect, and lets you generate trees fairly easily (which we do all the time in our tests):

var nodes = Builder<OrgUnit>.CreateListOfSize(1000);
nodes.TheFirst().Set(x => x.Parent, null)
     .TheRest().Set(x => x.Parent, () => nodes.Sample());

However, it doesn't let you (easily) create random graphs. If we wanted that, we'd have to do something like: Create all of the object references, then start applying the property modifications to them. This would actually accomplish what we wanted to do elsewhere too, where your lambda could take in the object you were building in a partially constructed state, so that your choice of value could depend on the value chosen. (i.e. give the professor a salary over a specific amount if they had tenure). However, this also may be over-kill.

I have a crude prototype of this, but I'd like your thoughts on how much of the above is worthwhile and if you have any thoughts about the implementation. (i.e., anything more than just a private list that we sample from?)

@robdmoore
Copy link
Member

Are there any scenarios that this lights up that you can't do with .BuildList() followed by a LINQ extension method to grab a random item? If not then it seems like, while it's useful, it's an orthogonal concern of the library?

@Quantumplation
Copy link
Contributor Author

If the builder has been used to construct several different objects, it could be more difficult. It's all doable, but it's overhead / boilerplate, whereas this library is meant (as I interpret it) to eliminate as much of that as possible.

Something that isn't as simple as .BuildList() and .Random() would be the tree example I gave. In that case, you're explicitly ensuring that everything generated is parented to something generated before it. Without this, you'd have to do something like:

    var nodes = Builder<OrgUnit>.CreateListOfSize(1000).BuildList();
    var workingSet = new List<OrgUnit>();
    workingSet.Add(nodes.First());
    foreach(var node in nodes)
    {
        node.Parent = workingSet.PickRandom();
        workingSet.Add(node);
    }

Yes, it's doable, but it seems to me to fit nicely within the concerns of the library: Reducing the burden of creating data for testing purposes.

@robdmoore
Copy link
Member

Ah yeah, fair enough.

I'll be honest I'm still a bit confused about what's going on in that code, but if you have a PoC to push up as a pull request then maybe it will make more sense?

@Quantumplation
Copy link
Contributor Author

Sure, I'll do so when I get off work today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants