【问题标题】:jqwik pairs of sorted array with some element of itjqwik 对已排序数组及其某些元素
【发布时间】:2020-05-18 13:58:49
【问题描述】:

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

@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[] 数组的一个元素。

【问题讨论】:

  • 你能显示你想在其中使用地图的属性吗?它可能会使目的更清晰,从而指向一种或另一种生成策略。

标签: java property-based-testing jqwik


【解决方案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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    • 2011-05-27
    相关资源
    最近更新 更多