jqwik pairs of sorted array with some element of it

北慕城南 提交于 2020-02-25 09:33:10

问题


Following code aims to generate random sorted array, and key as one element of that array. But I do not know the issue, the keys are not in the array?

@Provide
Arbitrary<Map<Integer, Integer[]>> llstPairs() {


  // sortedArrayGenerator is generattor that return Arbitrary<Integer[]> sorted values
  // and it works fine
  Arbitrary<Integer[]> vals = sortedArrayGenerator();

  Integer[] sample = vals.sample();

  Arbitrary<Integer> key = Arbitraries.samples(sample);


  return Arbitraries.maps(key,vals);

}

Why my keys are not in the array, I need the key to be one element of the Integer[] array.


回答1:


The one important thing you should be aware of is: "Never create your own sample. Let jqwik decide when to do that." In other words: Arbitrary.sample() is only for testing generators, e.g. in JShell, or using generators outside of jqwik properties.

What you need instead is Arbitrary.flatMap(). Flat mapping is needed whenever the result of one generator is needed to feed another generator. So your first try could be:

@Provide
Arbitrary<Map<Integer, Integer[]>> llstPairs() {
    Arbitrary<Integer[]> vals = sortedArrayGenerator().filter(array -> array.length > 0);

    return vals.flatMap(array -> {
        Arbitrary<Integer> keys = Arbitraries.of(array);
        return Arbitraries.maps(keys, vals);
    });

}

Two sidenotes:

  • I filter out empty arrays because they will make problems down the road
  • Read the javadoc for Arbitraries.sample()! It's not what you want which is Arbitraries.of().

However, it's not as easy because the generated array for the map is a different one than you used for the keys. You have to make sure that you use the exact same array when creating the map. So you might go with:

@Provide
Arbitrary<Map<Integer, Integer[]>> llstPairs() {
    Arbitrary<Integer[]> vals = sortedArrayGenerator().filter(array -> array.length > 0);

    return vals.flatMap(array -> {
        Arbitrary<Integer> keys = Arbitraries.of(array);
        Arbitrary<List<Integer>> listOfKeys = keys.list();
        return listOfKeys.map(lok -> {
            Map<Integer, Integer[]> map = new HashMap<>();
            for (Integer k : lok) {
                map.put(k, array);
            }
            return map;
        });
    });
}

which is quite involved given that - as I understand it - you don't really need the map but want a list of key-array-pairs. That's why I would go with this:

@Provide
Arbitrary<List<Tuple.Tuple2<Integer, Integer[]>>> listOfPairs() {
    Arbitrary<Integer[]> vals = sortedArrayGenerator().filter(array -> array.length > 0);
    return vals.flatMap(arrayOfInt -> {
        Arbitrary<Integer> key = Arbitraries.of(arrayOfInt);
        return key.map(k -> Tuple.of(k, arrayOfInt)).list();
    });
}

And here's a property to check that it does what it's supposed to do:

@Property(tries = 100)
void listOfPairs_keyIsInArray(@ForAll("listOfPairs") List<Tuple.Tuple2<Integer, Integer[]>> listOfPairs) {
    for (Tuple.Tuple2<Integer, Integer[]> pair : listOfPairs) {
        Integer key = pair.get1();
        Integer[] array = pair.get2();
        Assertions.assertThat(array).contains(key);
    }
}


来源:https://stackoverflow.com/questions/60028612/jqwik-pairs-of-sorted-array-with-some-element-of-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!