1

以下代码旨在生成随机排序的数组,并将键作为该数组的一个元素。但是我不知道问题,键不在数组中?

@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);

}

为什么我的键不在数组中,我需要键是 Integer[] 数组的一个元素。

4

1 回答 1

1

您应该注意的一件重要的事情是:“永远不要创建自己的样本。让 jqwik 决定何时这样做。” 换句话说:Arbitrary.sample()仅用于测试生成器,例如在 JShell 中,或使用 jqwik 属性之外的生成器。

你需要的是Arbitrary.flatMap(). 每当需要一个生成器的结果来馈送另一个生成器时,都需要平面映射。所以你的第一次尝试可能是:

@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);
    });

}

两个旁注:

但是,这并不容易,因为为地图生成的数组与用于键的数组不同。您必须确保在创建地图时使用完全相同的数组。所以你可以选择:

@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;
        });
    });
}

考虑到这一点 - 据我所知 - 你并不真正需要地图,但想要一个键数组对列表,这是相当复杂的。这就是为什么我会这样做:

@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();
    });
}

这里有一个属性来检查它是否做了它应该做的事情:

@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);
    }
}
于 2020-02-03T09:28:01.590 回答