Kotest - 生成无重复的详尽对象排列
Kotest - Generate exhaustive object permutations with no repeat
我希望能够生成详尽的对象排列。想象一下下面的对象
data class Person (name: String, age: Int)
出于测试目的,我想将 name
限制为 3
值。 Mohammad
、Nasir
、Rasul
和 age
到 4
值。 10
、20
、30
、40
。我想生成 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
生成器的方法。我 可以 做一些 post 处理并删除重复项,但我希望预先提供更可靠的独特内容。
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
错过了。
1 个基于@Tenfour04 评论的可能解决方案是使用 times
和 map
。尽管在我的字段中,映射变得很复杂,因为我们将要处理 Pairs
和 Pairs
以及 Pairs
。
"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")
}
}
}
您可以通过映射每个组件中的每个值并将它们组合成一个新的 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
我希望能够生成详尽的对象排列。想象一下下面的对象
data class Person (name: String, age: Int)
出于测试目的,我想将 name
限制为 3
值。 Mohammad
、Nasir
、Rasul
和 age
到 4
值。 10
、20
、30
、40
。我想生成 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
生成器的方法。我 可以 做一些 post 处理并删除重复项,但我希望预先提供更可靠的独特内容。
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
错过了。
1 个基于@Tenfour04 评论的可能解决方案是使用 times
和 map
。尽管在我的字段中,映射变得很复杂,因为我们将要处理 Pairs
和 Pairs
以及 Pairs
。
"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")
}
}
}
您可以通过映射每个组件中的每个值并将它们组合成一个新的 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