Skip to content

Best practice for delegating configurations? #272

@941design

Description

@941design

Hi,

How to properly delegate a generator configuration?

Assume MyObject has two attributes of the same type whose generators need to be configured. Let's say foo and bar are both integers, and I want to configure them with different ranges. I created a configuration annotation with fields fooMin, fooMax, barMin, and barMax, and a generator MyObjectGen that can be configured with MyObjectConf. In configure I want to delegate to sub-generators. What is the proper way to do this?

My solution works but does not feel right, because I also hat to create an implementation of @InRange in order to configure the inner generators. I know I could configure the inner generators with annotations, but that does not seem to be practical either (when I have a lot of test methods each requiring a unique configuration).

On the other hand, I like the usage of my implementation, because how the parameter is configured matches that of the built-in generated parameters.

What am I missing?
Thanks a lot!

@RunWith(JUnitQuickcheck.class)
public class MyObjectPropertiesTest {

    @Target({PARAMETER, FIELD, ANNOTATION_TYPE, TYPE_USE})
    @Retention(RUNTIME)
    @From(MyObjectGen.class)
    @GeneratorConfiguration
    @interface MyObjectConf {

        int fooMin() default 0;

        int fooMax() default 10;

        int barMin() default 0;

        int barMax() default 10;

    }

    public static class MyObject {

        private final int foo;
        private final int bar;

        public MyObject(int foo, int bar) {
            this.foo = foo;
            this.bar = bar;
        }

    }

    public static class MyObjectGen extends Generator<MyObject> {

        private final IntegerGenerator fooGen = new IntegerGenerator();
        private final IntegerGenerator barGen = new IntegerGenerator();

        public MyObjectGen() {
            super(MyObject.class);
        }

        public void configure(MyObjectConf config) {
            fooGen.configure(new InRangeBase() {
                @Override
                public String min() {
                    return String.valueOf(config.fooMin());
                }

                @Override
                public String max() {
                    return String.valueOf(config.fooMax());
                }
            });
            barGen.configure(new InRangeBase() {
                @Override
                public String min() {
                    return String.valueOf(config.barMin());
                }

                @Override
                public String max() {
                    return String.valueOf(config.barMax());
                }
            });
        }

        @Override
        public MyObject generate(SourceOfRandomness random, GenerationStatus status) {
            return new MyObject(fooGen.generate(random, status),
                                barGen.generate(random, status));
        }

    }

    @Property
    public void lessThanZero(@MyObjectConf(fooMin = -10, fooMax = -1) MyObject obj) {
        assertThat(obj.foo, lessThan(0));
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions