【问题标题】:Kotest - Generate exhaustive object permutations with no repeatKotest - 生成无重复的详尽对象排列
【发布时间】:2021-02-22 13:17:38
【问题描述】:

我希望能够生成详尽的对象排列。想象以下对象

data class Person (name: String, age: Int)

出于测试目的,我想将 name 限制为 3 值。 MohammadNasirRasulage4 值。 10203040。我想生成 12 个对象,其中每个名称都有 4 个年龄。

我可以生成一个arbitrary 绑定,但这并不能保证12 迭代每个都有一个唯一的对象。我必须增加迭代次数,并清除重复项。

    val list = Arb.bind(
        listOf("Nasir", "Rasul", "Mohammad").exhaustive(),
        listOf(10, 20, 30, 40).exhaustive()
    ) { name, age -> Person(name, age) }

    "Test person " - {
        runBlocking {
            list.checkAll(12) {
                System.out.println("Testing $it")
                assertTrue(it.age < 50)
            }
        }
    }

查看源代码,我似乎找不到方法。我希望社区中有人对此有需求。

谢谢。

注意:我正在寻找使用Exhaustive 生成器的方法,而不是Arb 生成器。我可以进行一些后期处理并删除重复项,但我希望预先获得更可靠、独特的东西。

Example outout:

Testing Person(name=Mohammad, age=40)
Testing Person(name=Nasir, age=20)
Testing Person(name=Rasul, age=20)
Testing Person(name=Rasul, age=30)
Testing Person(name=Mohammad, age=20)
Testing Person(name=Rasul, age=40)
Testing Person(name=Nasir, age=10)
Testing Person(name=Rasul, age=10)
Testing Person(name=Nasir, age=40)
Testing Person(name=Rasul, age=40)
Testing Person(name=Nasir, age=30)
Testing Person(name=Mohammad, age=30)

注意Rasul:40 是重复的。 Mohammad:10 错过了。

根据@Tenfour04 的评论,一种可能的解决方案是使用timesmap。尽管使用我的字段,映射变得很复杂,因为我们需要处理 PairsPairsPairs

    "Test cross product" - {
        val times = Exhaustive.collection(listOf("Nasir", "Rasul"))
            .times(Exhaustive.collection(listOf(10, 20)))
            .map { Person(it.first as String, it.second) }
        runBlocking {
            times.checkAll(4) {
                println("$it")
            }
        }
    }

【问题讨论】:

  • 这回答了你的问题? stackoverflow.com/questions/63064837/…
  • 感谢@Tenfour04。不完全的。我希望能够在对象的上下文中定义它,并且链接的构造似乎在外面。我会试一试,但乍一看,我认为它不会起作用。如果我发现相反的结果,我会报告。
  • 我认为它会起作用。我只需要将map 指向一个对象。谢谢@Tenfour04。虽然有超过 2 个属性,但由于使用 Pair,它开始变得令人费解。
  • 为什么不手动生成所有可能的组合val persons = names.flatMap { name -&gt; ages.map { Person(name, it) } }
  • @МихаилНафталь 我不确定我是否跟随。我将有一个数据结构,其中每个属性都有一组不同的值,一些枚举,一些其他有限集......如果我理解正确,如果只有两件事,你的建议就会奏效......跨度>

标签: kotlin kotest


【解决方案1】:

您可以通过映射每个组件中的每个值并将它们组合成一个新的 Exhaustive 来做到这一点。例如,如果您有三个组件,您想要生成所有组合:

fun <A, B, C, D> cartesian(
   a: Exhaustive<A>,
   b: Exhaustive<B>,
   c: Exhaustive<C>,
   f: (A, B, C) -> D
): Exhaustive<D> {
   val ds = a.values.flatMap { _a ->
      b.values.flatMap { _b ->
         c.values.map { _c ->
            f(_a, _b, _c)
         }
      }
   }
   return ds.exhaustive()
}

然后可以在测试中使用穷举(对于 arity-2 等)。

以下是您将如何将它用于您的个人示例。

val persons = cartesian(
   Exhaustive.collection(listOf("Nasir", "Rasul")),
   Exhaustive.collection(listOf(10, 20))
) { a, b -> Person(a, b) }

checkAll(persons) { person -> .... test here .... }

注意:上述功能存在于 Kotest 4.5 中,在撰写本文时尚未发布。 https://github.com/kotest/kotest/blob/master/kotest-property/src/commonMain/kotlin/io/kotest/property/exhaustive/cartesian.kt

【讨论】:

    猜你喜欢
    • 2014-03-15
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    相关资源
    最近更新 更多