Skip to content

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

Open

Description

@Quantumplation

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?)

Activity

  1. robdmoore commented on May 21, 2015

    @robdmoore
    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?

  2. Quantumplation commented on May 21, 2015

    @Quantumplation
    ContributorAuthor

    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.

  3. robdmoore commented on May 21, 2015

    @robdmoore
    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?

  4. Quantumplation commented on May 21, 2015

    @Quantumplation
    ContributorAuthor

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions