Code Monkey home page Code Monkey logo

teststack.dossier's People

Contributors

bringer128 avatar mwhelan avatar poyamanouchehri avatar quantumplation avatar robdmoore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

teststack.dossier's Issues

Looking for example of a builder that builds an object with a collections of child objects

I'm trying to use Dossier to build an object that maintains a collection of related objects, e.g. imagine an Order that encapsulates zero, one, or many OrderLine instances.

public class Order {
  public string OrderReference { get; set; }
  public List<OrderLine> OrderLines { get; } => new List<OrderLine>();
}

public class OrderLine {
  public string Sku { get; set; }
  public int Quantity { get; set; }
}

I'm assuming in this case I need to implement BuildObject manually for my OrderBuilder, in order to do a Get(x => x.OrderLines) and then call .AddRange() on the OrderLines property of the Order that I construct... however I'm getting an InvalidCastException trying to get from OrderLine[] to List<OrderLine>.

I could put up a full repro if that would help.

Create object list based in relation to ohter object list

Hi,
I am going to start using Dossier but I wonder if it could be useful in such scenario.
This is my actual code

var parser = new RegtoppParser(null, Instance, new List<string> { "aa.TMS" });

parser.Stops.AddRange(new List<StopsHPLLine>
    {
        new StopsHPLLine{Zone = 1, StopNumber = 1},
        new StopsHPLLine{Zone = 1, StopNumber = 2}
    }
    );

parser.TripPatterns.AddRange(new List<TripPatternsTMSLine>
    {
        new TripPatternsTMSLine{StopNumber = 1, ArrivalPlatform = 0},
        new TripPatternsTMSLine{StopNumber = 2, ArrivalPlatform = 0}
    }
    );

I would like to be able to do something like this:

//use autogenerated stopNumber and set Zone = 2 
parser.Stops.AddRange(
    StopsBuilder.CreateListOf(2)
        .All().WithZone(1)
        .BuildList();

);

//create tripPattern for each StopNumber from Stops and set ArrivalPlatform = 0
parser.TripPatterns.AddRange(
//don't know how to do it here
);

So could you give me an example how to create list of TripPatterns using values from Stops?

"Doesn't not matter" - typo on wiki page

Hi, there seems to be a typo on the following page: http://dossier.teststack.net/docs/anonymous-values-and-equivalence-classes

It says: " stealing cognitive load from the test reader while they figure out the value in fact doesn't not matter." and I believe it should be "stealing cognitive load from the test reader while they figure out the value in fact does not matter." or " stealing cognitive load from the test reader while they figure out the value in fact doesn't matter.". I am not a native speaker, though.

Calling TestDataBuilder.CreateListOfSize() when the builder have a constructor calls the constructor with one extra call

Given this POCO class:

public class Data
{
    public string Text {get;set;}
}

and this custom builder for the POCO class:

public class DataBuilder : TestDataBuilder<Data, DataBuilder>
{
    public DataBuilder ()
    {
        var builder = Set (x => x.Text, "Data!!!");
        if (builder == null)
            throw new Exception ("Should not happen !?!!");
    }
}

The calling site is:

IList<Data> dataList = DataBuilder.CreateListOfSize (1).BuildList ():

The exception gets thrown in the DataBuilder constructor since Set() returns null.

I found out that there were two calls to the constructor, the first one is for the proxy generated by CastleWindsor and the second is for the actual instance.

Creating objects with properties of complex types

Hi,
I am having some difficulties with creating objects that have properties defined as complex types. Can you guide me how to do it correctly?

Lets say there is a class:

public class JourneyPatternPoint
{
	public int PointSequenceNumber { get; set; }
	public int ArrivalTime { get; set; }
	
	public Point Point { get; set; }
	public TextString PointText { get; set; }
	public TextString DestinationText { get; set; }
}

And I want to initialize it with builder.

  1. var point = Builder<JourneyPatternPoint>.CreateNew().Build(); This will set all complex types to null. Is it by design?
  2. Is this only way to initialize complex types?
var point = Builder<JourneyPatternPoint>.CreateNew()
                        .Set(p => p.Point, Builder<Point>.CreateNew())
                        .Set(p => p.PointText, Builder<TextString>.CreateNew())
                        .Set(p => p.DestinationText, Builder<TextString>.CreateNew())
                        .Build();

Use builder in for constructor parameter

Hi,

I have a question about builders. I'm new with your project but I can't find any sample on how to do this.

I have an object called Project. It has a public constructor with a few parameters. One of the properties is a List<AddMemberCommand>. How can I use a builder for this parameter?

I've tried the generic builder and a custom builder but can't figure it out. Can you help me?

The AddMemberCommand has also an object in the constructor.

public class Project
{
    public Guid Id { get; private set; }

    public string Name { get; private set; }

    private Project() { }

    public Project(string name, List<AddMemberCommand> teamMembers)
    {
        Id = Guid.NewGuid();
        Name = name;
        //teamMembers.ForEach(AddMember);
    }
}

public class ProjectBuilder : TestDataBuilder<Project, ProjectBuilder>
{
    public virtual ProjectBuilder WithName(string name)
    {
        return Set(x => x.Name, name);
    }

    protected override Project BuildObject()
    {
        return new Project(
          Get(x => x.Name),
          new Builder<AddMemberCommand>()
        );
    }
}

public class AddMemberCommand
{
    public Member Member { get; private set; }

    public AddMemberCommand(Member member)
    {
        if (member == null)
        {
            throw new ArgumentNullException(nameof(member));
        }

        Member = member;
    }
}

Thanks

Pick is missing in nuget TestStack.Dossier 3.2.1

Hi,
I can see that Pick functionality was committed few months ago but it looks like it is not available in nuget version 3.2.1. Could you please verify it?

The type or namespace name 'Pick' does not exist in the namespace 'TestStack.Dossier.DataSources' (are you missing an assembly reference?)
The type or namespace name 'Picking' does not exist in the namespace 'TestStack.Dossier.DataSources' (are you missing an assembly reference?)

Question about usage scenarios

Hi Guys,

I'm just trying to setup some generic testing code that will have nbuilder construct objects, send them to an API and then pull them back to confirm that the API saved them right.

From the documentation on the homepage I could only really figure out that this library is just a more wordy / code heavy version of manually constructing the object and setting all the values or just using nbuilder directly.

I would like someone to help me understand the benefit of this package if possible so I don't miss an opportunity whilst constructing a test framework.

Can someone tell me how this improves our testing experience over the base nbuilder lib?

Ability to specify a Seed value for all random generation

One of the big concerns my coworkers have over using this library is how reproducible the results are: if it randomly generates some data that causes a test to fail, and we can't get it to produce the same data again, we won't be able to effectively debug the issue.

I'm not overly concerned with this, as I don't see that being too frequent of an issue; it seems to me the kinds of data this library fills in are generic enough to not lead to the kinds of bugs that aren't super easy to spot just looking at the code.

How easy would it be to thread a seed value through the randomly generated parts of this library?

new() constraint on TestDataBuilder<,>

This makes me incredibly sad.

I want to be able to require some values when creating my builder (otherwise my domain invariants will cause my BuildObject method to fall over). But I can't use a parameterised constructor because I'm guessing Dossier uses reflection or something? Probably a totally valid reason, but still. Sad.

Unclear sort order

Hello again!

It is unclear to me in what order the .With lambdas are applied...

For example, I have

public static class Depots.SomeObj
{
    public static IListBuilder<SomeObjBuilder> RandomList(int n)
    {
        return CreateListOfSize(n)
          .All()
             .With(x => x.SomeCustomization("RandomDefault"));
    }
}

and then

var listBuilder = Depots.SomeObj.RandomList(10)
    .All()
        .With(x => x.SomeCustomization("Override"));

and the order they are executed is difficult to quantify. It seems the first time listBuilder.Build() is called, it executes Override and then RandomDefault, but the second time, it's the other way around.

Support for nested properties

Currently Set(x => x.Parent.Child) will store in the underlying dictionary under the key Child rather than Parent.Child so if you then have Set(x => x.Parent2.Child) that will conflict.

I've seen this trip people up multiple times before - it's not intuitive.

Has() should check for nullable .HasValue

It would be good if the Has() method tested nullable types specifically such that code like this was not necessary:

if (Has(x => x.OrderIndex) && Get(x => x.OrderIndex).HasValue)

Add ITestDataBuilder<TObject> interface, missing after migration from NTestDataBuilder

I found this interface useful to create a extension method for seeding a DB context directly with builders.

e.g.

public static async Task<T> SaveAsync<T>(this IDbContext context, ITestDataBuilder<T> builder)
    where T : class
{
    var entity = builder.Build();
    context.Set<T>().Add(entity);
    await context.SaveAsync();
    return entity;
}

It was in NTestDataBuilder, however was removed for some reason in TestStack.Dossier. The change wasn't listed in BREAKING_CHANGES.md

I'll raise a PR for this soon.

Default BuildObject implementation using reflection

Automatically build an object by reflecting for a constructor with the most params and getting each by looking for a property of the same name (kinda like AutoFixture, but this would use the ability to customise the object(s).

This would be the default behaviour for BuildObject - you can then override it as soon as you get a more complex example.

This just makes it even more easy to quickly create a builder.

Might be more complex than it's worth though? It doesn't take long to create the BuildObject method...

RFQ - Weigh in on whether the implicit operator (negating need for .Build()) is confusing or useful

I'm building a user like var antUser = new UserBuilder().WithUniqueName("ant"); and its failing a test. When I add the explicit build eg var antUser = new UserBuilder().WithUniqueName("ant").Build(); the test passes.

What I think is happening is a combination of two things:

  • The automagic value assignment of my Id field, and
  • The implicit operator which is calling BuildObject() internally

The failure is due to the same antUser being used twice in the test setup and I'm expecting the identity of said User to be the same with both usages of the instance, only it's not! The Id is different every time the implicit cast happens.

This is a pretty big deal and I think most devs would expect the identity/equality to behave the same way I am.

The implicit operator is misleading in that it allows the dev to think they don't really need to call .Build() explicitly (yay! saved banging a few keys) and so they don't. It's not obvious that the fix is to call .Build(). And then when you figure it out it seems smelly that you need to be aware of this peculiar detail.

Thoughts?

ListBuilder proxy objects don't override "Set" method

The "Set" method is a convenient way to make changes to your builder objects without having to write a different method for every field on your object. However, when you are working with the ListBuilder proxy objects (the dynamic types which derive from existing builders), they don't override the Set method. This means that the following code:

    var customers = 
        CustomerBuilder.CreateListOfSize(10)
            .All().Set(c => c.FirstName, "test");

Is not working as expected, and instead has to be

    var customers = 
        CustomerBuilder.CreateListOfSize(10)
            .All().With(cb => cb.Set(c => c.FirstName, "test"));

Any way we can get the proxy generation to override the Set method as well?

Setting defaults in constructor when creating lists causes exception

Hi,

this code will raise a System.ArgumentNullException:

    public class Test
    {
        public int SetMe { get; set; }
    }

    public class TestBuilder : TestDataBuilder<Test, TestBuilder>
    {
        public TestBuilder()
        {
            this.Set(x => x.SetMe, 5);
        }
    }

    public class TestSpecification
    {
        Establish context = () =>
            {
                var test = TestBuilder.CreateListOfSize(2).BuildList();
            };
    }

this succeeds:

var test = new TestBuilder().Build();

Any ideas? Thanks.

Licence question

Hey @robdmoore, which type of licence is Dossier under?

The text reads like MIT, but I'd need to confirm to appease the overlords ;)

Building lists of relational database entities

To give an example, I would like to build the following database entities for my tests:

public class Driver
{
  public Guid Id { get; set; }
  public IEnumerable<Card> Cards { get; set; }
}

public class Card
{
  public string RFID { get set; }
  public Driver Owner { get;set; }
}

I have created Builders for both entities:

var driver = new DriverBuilder()
    .WithId(...)
    .Build();

var card = new CardBuilder()
    .WithRFID(...)
    .WithDriver(driver)
    .Build();

The WithDriver() method is as follows:

public virtual CardBuilder WithDriver(Driver driver)
{
    return Set(x => x.Driver, driver);
}

This correctly sets the Driver navigation property on the Card being built, however, how do I also add the Card to-be-built to the Cards property on the Driver??

I know I must be missing something because I feel like I'm chasing my tail!

Thank you

Overriding defaults set in constructor

I'm not sure how you would solve this, but if you set some field in your constructor, Dossier overrides it with what it thinks should be the default. This is particularly annoying with collections, since the default Dossier chooses is to set collection properties to null, rather than an empty collection. The workaround we're using is to override BuildObject and call .Set(GetOrDefault() ?? EmptyCollection) on every collection field.

Some possible solutions that I see:

  • Some way to indicate that Dossier should skip certain fields, unless someone's called Set on them
  • Make all fields opt-in, and provide an easy way to say "give this a sensible default"
  • Read the value of a field first, and if it's not the default value for that field, then set it to some reasonable default
  • Change the handling so that an empty list is the default for ICollection properties, Enumerable.Empty is the default for IEnumerable properties, etc.

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

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.