six2six / fixture-factory

Generator fake objects from a template
Apache License 2.0
445 stars 88 forks source link

Unique option in one-to-many relationship #67

Closed viniciusffj closed 9 years ago

viniciusffj commented 9 years ago

Pull request for issue https://github.com/six2six/fixture-factory/issues/65.

Usage

Just call unique() after has(n) in template definition:

Fixture.of(Programmer.class).addTemplate("valid", new Rule() {{
    add("name", firstName());
    add("skills", has(2).unique().of(Skill.class, "valid"));
}});

Fixture.of(Skill.class).addTemplate("valid", new Rule() {{
    add("name", random("Java", "JavaScript"));
}});

It is possible to pass to unique the maximum times to try generating a unique value (the default is 10):

Fixture.of(Programmer.class).addTemplate("valid_custom_retry", new Rule() {{
    add("name", firstName());
    add("skills", has(2).unique(8).of(Skill.class, "valid"));
}});
nykolaslima commented 9 years ago

Hello @viniciusffj. Thank you for sending us this PR.

I don't like too much about trying to generate a unique value multiple times. I was thinking in unique to AtomicFunction and not to AssociationFunction. This way, we could guarantee the uniqueness without have to try many times.

e.g.

Fixture.of(Skill.class).addTemplate("valid", new Rule() {{
    add("name", unique(random("Java", "JavaScript")));
}});

This way, we could guarantee that we will only generate Skills with unique names. But, in this definition, we can only generate 2 Skills, because we only have defined 2 possible names.

Fixture.from(Skill.class).gimme(3, "valid"); The code above will throw some exception like: NoMoreUniqueValuesException -> there is no more possible values for field 'name' (We need to think a better name)

What do you guys think about it? @ahirata @aparra

aparra commented 9 years ago

Hi @viniciusffj. First of all, many thanks for PR.

Same considerations about that:

Fixture.of(Programmer.class).addTemplate("valid", new Rule() {{
    add("name", firstName());
    add("skills", has(2).unique().of(Skill.class, "valid"));
}});

I Like this DSL, but this implementation is some confused: It is possible to pass to unique the maximum times to try generating a unique value (the default is 10):

Fixture.of(Programmer.class).addTemplate("valid_custom_retry", new Rule() {{
    add("name", firstName());
    add("skills", has(2).unique(8).of(Skill.class, "valid"));
}});

First of all, your DSL is broken. I understand that you have tried reuse the function that generate objects and drop repeated. But you need use this configuration has(2).unique() to choose the strategy to generate objects. When you generate a object x, you never more can generate x, if this rule is not respected you have introduced an in-determinism in your test suite. For real, you cannot determine if a AssociationFunction can generate different instances.

Please, reconsider your implementation, think about @nykolaslima example and try introduce a limit for your request. It is mandatory for this constructions works with limit data sets, like Enums or datas provided to random function.

Please, let me know if you have any question. I am looking forward for your next PR. Unique is a cool feature.