How to use edgecase method of io.kotest.property.arbitrary.arbs class

Best Kotest code snippet using io.kotest.property.arbitrary.arbs.edgecase

builders.kt

Source:builders.kt Github

copy

Full Screen

...44/**45 * Creates a new [Arb] that performs no shrinking, uses the given edge cases and46 * generates values from the given function.47 */48fun <A> arbitrary(edgecases: List<A>, fn: suspend ArbitraryBuilderContext.(RandomSource) -> A): Arb<A> =49 object : Arb<A>() {50 override fun edgecase(rs: RandomSource): A? = if (edgecases.isEmpty()) null else edgecases.random(rs.random)51 override fun sample(rs: RandomSource): Sample<A> = delegate.sample(rs)52 private val delegate = arbitraryBuilder { rs -> fn(rs) }53 }54/**55 * Creates a new [Arb] that performs shrinking using the supplied [Shrinker], uses the given edge cases and56 * generates values from the given function.57 */58fun <A> arbitrary(59 edgecases: List<A>,60 shrinker: Shrinker<A>,61 fn: suspend ArbitraryBuilderContext.(RandomSource) -> A62): Arb<A> = object : Arb<A>() {63 override fun edgecase(rs: RandomSource): A? = if (edgecases.isEmpty()) null else edgecases.random(rs.random)64 override fun sample(rs: RandomSource): Sample<A> = delegate.sample(rs)65 private val delegate = arbitraryBuilder(shrinker) { rs -> fn(rs) }66}67/**68 * Creates a new [Arb] that generates edge cases from the given [edgecaseFn] function69 * and generates samples from the given [sampleFn] function.70 */71fun <A> arbitrary(72 edgecaseFn: (RandomSource) -> A?,73 sampleFn: suspend ArbitraryBuilderContext.(RandomSource) -> A74): Arb<A> =75 object : Arb<A>() {76 override fun edgecase(rs: RandomSource): A? = edgecaseFn(rs)77 override fun sample(rs: RandomSource): Sample<A> = delegate.sample(rs)78 private val delegate: Arb<A> = arbitraryBuilder { rs -> sampleFn(rs) }79 }80/**81 * Creates a new [Arb] that generates edge cases from the given [edgecaseFn] function,82 * performs shrinking using the supplied [Shrinker], and generates samples from the given [sampleFn] function.83 */84fun <A> arbitrary(85 edgecaseFn: (RandomSource) -> A?,86 shrinker: Shrinker<A>,87 sampleFn: suspend ArbitraryBuilderContext.(RandomSource) -> A88): Arb<A> =89 object : Arb<A>() {90 override fun edgecase(rs: RandomSource): A? = edgecaseFn(rs)91 override fun sample(rs: RandomSource): Sample<A> = delegate.sample(rs)92 private val delegate: Arb<A> = arbitraryBuilder(shrinker) { rs -> sampleFn(rs) }93 }94/**95 * Creates a new [Arb] that performs no shrinking, has no edge cases and96 * generates values from the given function.97 */98suspend inline fun <A> generateArbitrary(99 crossinline fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A100): Arb<A> = suspendArbitraryBuilder { rs -> fn(rs) }101/**102 * Creates a new [Arb] that performs shrinking using the supplied [Shrinker], has no edge cases and103 * generates values from the given function.104 */105suspend inline fun <A> generateArbitrary(106 shrinker: Shrinker<A>,107 crossinline fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A108): Arb<A> = suspendArbitraryBuilder(shrinker, null) { rs -> fn(rs) }109/**110 * Creates a new [Arb] that classifies the generated values using the supplied [Classifier], has no edge cases and111 * generates values from the given function.112 */113suspend inline fun <A> generateArbitrary(114 classifier: Classifier<A>,115 crossinline fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A116): Arb<A> = suspendArbitraryBuilder(null, classifier) { rs -> fn(rs) }117/**118 * Creates a new [Arb] that performs shrinking using the supplied [Shrinker],119 * classifies the generated values using the supplied [Classifier], has no edge cases and120 * generates values from the given function.121 */122suspend inline fun <A> generateArbitrary(123 shrinker: Shrinker<A>,124 classifier: Classifier<A>,125 crossinline fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A126): Arb<A> = suspendArbitraryBuilder(shrinker, classifier) { rs -> fn(rs) }127/**128 * Creates a new [Arb] that performs no shrinking, uses the given edge cases and129 * generates values from the given function.130 */131suspend inline fun <A> generateArbitrary(132 edgecases: List<A>,133 crossinline fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A134): Arb<A> = suspendArbitraryBuilder(null, null,135 if (edgecases.isEmpty()) null else { rs -> edgecases.random(rs.random) }136) { rs -> fn(rs) }137/**138 * Creates a new [Arb] that performs shrinking using the supplied [Shrinker], uses the given edge cases and139 * generates values from the given function.140 */141suspend inline fun <A> generateArbitrary(142 edgecases: List<A>,143 shrinker: Shrinker<A>,144 crossinline fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A145): Arb<A> = suspendArbitraryBuilder(146 shrinker,147 null,148 if (edgecases.isEmpty()) null else { rs -> edgecases.random(rs.random) }149) { rs -> fn(rs) }150/**151 * Creates a new [Arb] that generates edge cases from the given [edgecaseFn] function152 * and generates samples from the given [sampleFn] function.153 */154suspend inline fun <A> generateArbitrary(155 crossinline edgecaseFn: (RandomSource) -> A?,156 crossinline sampleFn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A157): Arb<A> {158 val delegate: Arb<A> = suspendArbitraryBuilder { rs -> sampleFn(rs) }159 return object : Arb<A>() {160 override fun edgecase(rs: RandomSource): A? = edgecaseFn(rs)161 override fun sample(rs: RandomSource): Sample<A> = delegate.sample(rs)162 }163}164/**165 * Creates a new [Arb] that generates edge cases from the given [edgecaseFn] function,166 * performs shrinking using the supplied [Shrinker], and generates samples from the given [sampleFn] function.167 */168suspend inline fun <A> generateArbitrary(169 crossinline edgecaseFn: (RandomSource) -> A?,170 shrinker: Shrinker<A>,171 crossinline sampleFn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A172): Arb<A> {173 val delegate: Arb<A> = suspendArbitraryBuilder(shrinker) { rs -> sampleFn(rs) }174 return object : Arb<A>() {175 override fun edgecase(rs: RandomSource): A? = edgecaseFn(rs)176 override fun sample(rs: RandomSource): Sample<A> = delegate.sample(rs)177 }178}179/**180 * Creates a new [Arb] using [Continuation] using a stateless [builderFn].181 *182 * This function accepts an optional [shrinker], [classifier], and [edgecaseFn]. These parameters183 * will be passed to [ArbitraryBuilder].184 */185fun <A> arbitraryBuilder(186 shrinker: Shrinker<A>? = null,187 classifier: Classifier<A>? = null,188 edgecaseFn: EdgecaseFn<A>? = null,189 builderFn: suspend ArbitraryBuilderContext.(RandomSource) -> A190): Arb<A> = object : Arb<A>() {191 override fun edgecase(rs: RandomSource): A? = singleShotArb(SingleShotGenerationMode.Edgecase, rs).edgecase(rs)192 override fun sample(rs: RandomSource): Sample<A> = singleShotArb(SingleShotGenerationMode.Sample, rs).sample(rs)193 override val classifier: Classifier<out A>? = classifier194 /**195 * This function generates a new instance of a single shot arb.196 * DO NOT CACHE THE [Arb] returned by this function.197 *198 * This needs to be a function because at time of writing, Kotlin 1.5's [Continuation] is single shot.199 * With arbs, we ideally need multishot. To rerun [builderFn], we need to "reset" the continuation.200 *201 * The current way we do it is to recreate a fresh [SingleShotArbContinuation] instance that202 * will provide another single shot Arb. Hence the reason why this function is invoked203 * on every call to [sample] / [edgecase].204 */205 private fun singleShotArb(mode: SingleShotGenerationMode, rs: RandomSource): Arb<A> {206 val restrictedContinuation = SingleShotArbContinuation.Restricted(mode, rs) {207 /**208 * At the end of the suspension we got a generated value [A] as a comprehension result.209 * This value can either be a sample, or an edgecase.210 */211 val value: A = builderFn(rs)212 /**213 * Here we point A into an Arb<A> with the appropriate enrichments including214 * [Shrinker], [Classifier], and [EdgecaseFn]. When edgecase returns null, we pass the generated value215 * to the edgecase function so to make sure we retain all arbs' edgecases inside the comprehension.216 */217 ArbitraryBuilder({ value }, classifier, shrinker, { rs -> edgecaseFn?.invoke(rs) ?: value }).build()218 }219 return with(restrictedContinuation) {220 this@with.createSingleShotArb()221 }222 }223}224/**225 * Creates a new suspendable [Arb] using [Continuation] using a stateless [fn].226 *227 * This function accepts an optional [shrinker], [classifier], and [edgecaseFn]. These parameters228 * will be passed to [ArbitraryBuilder].229 */230suspend fun <A> suspendArbitraryBuilder(231 shrinker: Shrinker<A>? = null,232 classifier: Classifier<A>? = null,233 edgecaseFn: EdgecaseFn<A>? = null,234 fn: suspend GenerateArbitraryBuilderContext.(RandomSource) -> A235): Arb<A> = suspendCoroutineUninterceptedOrReturn { cont ->236 val arb = object : Arb<A>() {237 override fun edgecase(rs: RandomSource): A? = singleShotArb(SingleShotGenerationMode.Edgecase, rs).edgecase(rs)238 override fun sample(rs: RandomSource): Sample<A> = singleShotArb(SingleShotGenerationMode.Sample, rs).sample(rs)239 override val classifier: Classifier<out A>? = classifier240 /**241 * This function generates a new instance of a single shot arb.242 * DO NOT CACHE THE [Arb] returned by this function.243 *244 * This needs to be a function because at time of writing, Kotlin 1.5's [Continuation] is single shot.245 * With arbs, we ideally need multishot. To rerun [fn], we need to "reset" the continuation.246 *247 * The current way we do it is to recreate a fresh [SingleShotArbContinuation] instance that248 * will provide another single shot Arb. Hence the reason why this function is invoked249 * on every call to [sample] / [edgecase].250 */251 private fun singleShotArb(genMode: SingleShotGenerationMode, rs: RandomSource): Arb<A> {252 val suspendableContinuation = SingleShotArbContinuation.Suspendedable(genMode, rs, cont.context) {253 /**254 * At the end of the suspension we got a generated value [A] as a comprehension result.255 * This value can either be a sample, or an edgecase.256 */257 val value: A = fn(rs)258 /**259 * Here we point A into an Arb<A> with the appropriate enrichments including260 * [Shrinker], [Classifier], and [EdgecaseFn]. When edgecase returns null, we pass the generated value261 * to the edgecase function so to make sure we retain all arbs' edgecases inside the comprehension.262 */263 ArbitraryBuilder({ value }, classifier, shrinker, { rs -> edgecaseFn?.invoke(rs) ?: value }).build()264 }265 return with(suspendableContinuation) {266 this@with.createSingleShotArb()267 }268 }269 }270 cont.resume(arb)271}272typealias SampleFn<A> = (RandomSource) -> A273typealias EdgecaseFn<A> = (RandomSource) -> A?274class ArbitraryBuilder<A>(275 private val sampleFn: SampleFn<A>,276 private val classifier: Classifier<A>?,277 private val shrinker: Shrinker<A>?,278 private val edgecaseFn: EdgecaseFn<A>?,279) {280 companion object {281 fun <A> create(f: (RandomSource) -> A): ArbitraryBuilder<A> = ArbitraryBuilder(f, null, null, null)282 }283 fun withClassifier(classifier: Classifier<A>) = ArbitraryBuilder(sampleFn, classifier, shrinker, edgecaseFn)284 fun withShrinker(shrinker: Shrinker<A>) = ArbitraryBuilder(sampleFn, classifier, shrinker, edgecaseFn)285 fun withEdgecaseFn(edgecaseFn: EdgecaseFn<A>) = ArbitraryBuilder(sampleFn, classifier, shrinker, edgecaseFn)286 fun withEdgecases(edgecases: List<A>) = ArbitraryBuilder(sampleFn, classifier, shrinker) {287 if (edgecases.isEmpty()) null else edgecases.random(it.random)288 }289 fun build() = object : Arb<A>() {290 override val classifier: Classifier<out A>? = this@ArbitraryBuilder.classifier291 override fun edgecase(rs: RandomSource): A? = edgecaseFn?.invoke(rs)292 override fun sample(rs: RandomSource): Sample<A> {293 val sample = sampleFn(rs)294 return if (shrinker == null) Sample(sample) else sampleOf(sample, shrinker)295 }296 }297}298interface BaseArbitraryBuilderSyntax {299 /**300 * [bind] returns the generated value of an arb. This can either be a sample or an edgecase.301 */302 suspend fun <T> Arb<T>.bind(): T303}304@RestrictsSuspension305interface ArbitraryBuilderContext : BaseArbitraryBuilderSyntax306interface GenerateArbitraryBuilderContext : BaseArbitraryBuilderSyntax307enum class SingleShotGenerationMode { Edgecase, Sample }308sealed class SingleShotArbContinuation<F : BaseArbitraryBuilderSyntax, A>(309 override val context: CoroutineContext,310 private val generationMode: SingleShotGenerationMode,311 private val randomSource: RandomSource,312 private val fn: suspend F.() -> Arb<A>313) : Continuation<Arb<A>>, BaseArbitraryBuilderSyntax {314 class Restricted<A>(315 genMode: SingleShotGenerationMode,316 rs: RandomSource,317 fn: suspend ArbitraryBuilderContext.() -> Arb<A>318 ) : SingleShotArbContinuation<ArbitraryBuilderContext, A>(EmptyCoroutineContext, genMode, rs, fn),319 ArbitraryBuilderContext320 class Suspendedable<A>(321 genMode: SingleShotGenerationMode,322 rs: RandomSource,323 override val context: CoroutineContext,324 fn: suspend GenerateArbitraryBuilderContext.() -> Arb<A>325 ) : SingleShotArbContinuation<GenerateArbitraryBuilderContext, A>(context, genMode, rs, fn),326 GenerateArbitraryBuilderContext327 private lateinit var returnedArb: Arb<A>328 private var hasExecuted: Boolean = false329 override fun resumeWith(result: Result<Arb<A>>) {330 hasExecuted = true331 result.map { resultArb -> returnedArb = resultArb }.getOrThrow()332 }333 override suspend fun <T> Arb<T>.bind(): T = when (generationMode) {334 SingleShotGenerationMode.Edgecase -> this.edgecase(randomSource) ?: this.sample(randomSource).value335 SingleShotGenerationMode.Sample -> this.sample(randomSource).value336 }337 /**338 * It's important to understand that at the time of writing (Kotlin 1.5) [Continuation] is single shot,339 * i.e. it can only be resumed once. When it's possible to create multishot continuations in the future, we340 * might be able to simplify this further.341 *342 * The aforementioned limitation means the [Arb] that we construct through this mechanism can only be used343 * to generate exactly one value. Hence, to recycle and rerun the specified composed transformation,344 * we need to recreate the [SingleShotArbContinuation] instance and call [createSingleShotArb] again.345 */346 fun F.createSingleShotArb(): Arb<A> {347 require(!hasExecuted) { "continuation has already been executed, if you see this error please raise a bug report" }348 val result = fn.startCoroutineUninterceptedOrReturn(this@createSingleShotArb, this@SingleShotArbContinuation)...

Full Screen

Full Screen

BuilderTest.kt

Source:BuilderTest.kt Github

copy

Full Screen

...16import io.kotest.property.arbitrary.IntShrinker17import io.kotest.property.arbitrary.alphanumeric18import io.kotest.property.arbitrary.arbitrary19import io.kotest.property.arbitrary.constant20import io.kotest.property.arbitrary.edgecases21import io.kotest.property.arbitrary.flatMap22import io.kotest.property.arbitrary.generateArbitrary23import io.kotest.property.arbitrary.int24import io.kotest.property.arbitrary.map25import io.kotest.property.arbitrary.next26import io.kotest.property.arbitrary.numbers.IntClassifier27import io.kotest.property.arbitrary.single28import io.kotest.property.arbitrary.string29import io.kotest.property.arbitrary.take30import io.kotest.property.arbitrary.withEdgecases31import kotlinx.coroutines.withContext32import kotlin.coroutines.CoroutineContext33import kotlin.random.nextInt34class BuilderTest : FunSpec() {35 init {36 test("custom arb test") {37 arbitrary {38 it.random.nextInt(3..6)39 }.take(1000).toSet() shouldBe setOf(3, 4, 5, 6)40 }41 test("composition of arbs") {42 data class Person(val name: String, val age: Int)43 val personArb = arbitrary { rs ->44 val name = Arb.string(10..12).next(rs)45 val age = Arb.int(21, 150).next(rs)46 Person(name, age)47 }48 personArb.next().name.shouldHaveLengthBetween(10, 12)49 personArb.next().age.shouldBeBetween(21, 150)50 }51 context("arbitrary builder using restricted continuation") {52 test("should be stack safe") {53 val arb: Arb<Int> = arbitrary {54 (1..100000).map {55 Arb.int().bind()56 }.last()57 }58 val result = shouldNotThrowAny { arb.single(RandomSource.seeded(1234)) }59 result shouldBe -148693402360 }61 test("should be equivalent to chaining flatMaps") {62 val arbFlatMaps: Arb<String> =63 Arb.string(5, Codepoint.alphanumeric()).withEdgecases("edge1", "edge2").flatMap { first ->64 Arb.int(1..9).withEdgecases(5).flatMap { second ->65 Arb.int(101..109).withEdgecases(100 + second).map { third ->66 "$first $second $third"67 }68 }69 }70 val arb: Arb<String> = arbitrary {71 val first = Arb.string(5, Codepoint.alphanumeric()).withEdgecases("edge1", "edge2").bind()72 val second = Arb.int(1..9).withEdgecases(5).bind()73 val third = Arb.int(101..109).withEdgecases(100 + second).bind()74 "$first $second $third"75 }76 val flatMapsResult = arbFlatMaps.generate(RandomSource.seeded(12345L)).take(100).map { it.value }.toList()77 val builderResult = arb.generate(RandomSource.seeded(12345L)).take(100).map { it.value }.toList()78 // should be equivalent79 builderResult shouldContainExactly flatMapsResult80 }81 test("should bind edgecases") {82 val arb: Arb<String> = arbitrary {83 val first = Arb.string(5, Codepoint.alphanumeric()).withEdgecases("edge1", "edge2").bind()84 val second = Arb.int(1..9).withEdgecases(5).bind()85 val third = Arb.int(101..109).withEdgecases(100 + second, 109).bind()86 "$first $second $third"87 }88 arb.edgecases() shouldContainExactlyInAnyOrder setOf(89 "edge1 5 105",90 "edge2 5 105",91 "edge1 5 109",92 "edge2 5 109",93 )94 }95 test("should preserve edgecases of dependent arbs, even when intermideary arb(s) have no edgecases") {96 val arb: Arb<String> = arbitrary {97 val first = Arb.string(5, Codepoint.alphanumeric()).withEdgecases("edge1", "edge2").bind()98 val second = Arb.int(1..4).withEdgecases(emptyList()).bind()99 val third = Arb.int(101..109).withEdgecases(100 + second).bind()100 "$first $second $third"101 }102 arb.edgecases() shouldContainExactlyInAnyOrder setOf(103 "edge1 1 101",104 "edge1 2 102",105 "edge1 3 103",106 "edge1 4 104",107 "edge2 1 101",108 "edge2 2 102",109 "edge2 3 103",110 "edge2 4 104"111 )112 }113 test("should assign edgecases") {114 val edges = setOf("edge1", "edge2")115 val arb = arbitrary(edges.toList()) { "abcd" }116 arb.edgecases() shouldContainExactlyInAnyOrder edges117 }118 test("should assign edgecases and shrinker") {119 val shrinker = IntShrinker(1..5)120 val edges = setOf(1, 2)121 val arb = arbitrary(edges.toList(), shrinker) { 5 }122 arb.edgecases() shouldContainExactlyInAnyOrder edges123 arb.sample(RandomSource.seeded(1234L)).shrinks.children.value.map { it.value() } shouldBe shrinker.shrink(5)124 }125 test("should use shrinker when provided") {126 val shrinker = IntShrinker(1..5)127 val arb = arbitrary(shrinker) { 5 }128 arb.classifier.shouldBeNull()129 val shrinks = arb.sample(RandomSource.seeded(1234L)).shrinks130 shrinks.children.value.map { it.value() } shouldContainExactly shrinker.shrink(5)131 }132 test("should use classifier when provided") {133 val classifier = IntClassifier(1..5)134 val arb = arbitrary(classifier) { 5 }135 arb.classifier shouldBeSameInstanceAs classifier136 }137 test("should use classifier and shrinker when provided") {138 val shrinker = IntShrinker(1..5)139 val classifier = IntClassifier(1..5)140 val arb = arbitrary(shrinker, classifier) { 5 }141 arb.classifier shouldBeSameInstanceAs classifier142 val shrinks = arb.sample(RandomSource.seeded(1234L)).shrinks143 shrinks.children.value.map { it.value() } shouldContainExactly shrinker.shrink(5)144 }145 test("should use edgecase function when provided") {146 val arb = arbitrary({ 5 }) { 10 }147 arb.edgecases() shouldContainExactlyInAnyOrder setOf(5)148 }149 test("should use edgecase function and shrinker when provided") {150 val shrinker = IntShrinker(1..5)151 val arb = arbitrary({ 5 }, shrinker) { 10 }152 arb.edgecases() shouldContainExactlyInAnyOrder setOf(5)153 val shrinks = arb.sample(RandomSource.seeded(1234L)).shrinks154 shrinks.children.value.map { it.value() } shouldContainExactly shrinker.shrink(10)155 }156 test("should support .bind() syntax") {157 val arb = Arb.constant(5)158 val shrinker = IntShrinker(1..5)159 val classifier = IntClassifier(1..5)160 arbitrary { arb.bind() }.single() shouldBe 5161 arbitrary(shrinker) { arb.bind() }.single() shouldBe 5162 arbitrary(classifier) { arb.bind() }.single() shouldBe 5163 arbitrary(shrinker, classifier) { arb.bind() }.single() shouldBe 5164 arbitrary(listOf(5)) { arb.bind() }.single() shouldBe 5165 arbitrary({ 5 }) { arb.bind() }.single() shouldBe 5166 arbitrary({ 5 }, shrinker) { arb.bind() }.single() shouldBe 5167 }168 }169 context("suspend arbitrary builder with unrestricted continuation") {170 suspend fun combineAsString(vararg values: Any?): String = values.joinToString(" ")171 test("should build arb on the parent coroutine context") {172 val arb = withContext(Foo("hello")) {173 generateArbitrary {174 val hello = coroutineContext[Foo]?.value175 val world = arbitrary { "world" }.bind()176 val first = Arb.int(1..10).bind()177 val second = Arb.int(11..20).bind()178 combineAsString(hello, world, first, second)179 }180 }181 arb.generate(RandomSource.seeded(1234L)).take(4).toList().map { it.value } shouldContainExactly listOf(182 "hello world 2 20",183 "hello world 6 12",184 "hello world 7 19",185 "hello world 9 13"186 )187 }188 test("should bind edgecases") {189 val arb: Arb<String> = generateArbitrary {190 val first = Arb.string(5, Codepoint.alphanumeric()).withEdgecases("edge1", "edge2").bind()191 val second = Arb.int(1..9).withEdgecases(5).bind()192 val third = Arb.int(101..109).withEdgecases(100 + second, 109).bind()193 combineAsString(first, second, third)194 }195 arb.edgecases() shouldContainExactlyInAnyOrder setOf(196 "edge1 5 105",197 "edge2 5 105",198 "edge1 5 109",199 "edge2 5 109",200 )201 }202 test("should preserve edgecases of dependent arbs, even when intermideary arb(s) have no edgecases") {203 val arb: Arb<String> = generateArbitrary {204 val first = Arb.string(5, Codepoint.alphanumeric()).withEdgecases("edge1", "edge2").bind()205 val second = Arb.int(1..4).withEdgecases(emptyList()).bind()206 val third = Arb.int(101..109).withEdgecases(100 + second).bind()207 combineAsString(first, second, third)208 }209 arb.edgecases() shouldContainExactlyInAnyOrder setOf(210 "edge1 1 101",211 "edge1 2 102",212 "edge1 3 103",213 "edge1 4 104",214 "edge2 1 101",215 "edge2 2 102",216 "edge2 3 103",217 "edge2 4 104"218 )219 }220 test("should propagate exception") {221 val throwingArb = generateArbitrary {222 val number = Arb.int(1..4).withEdgecases(emptyList()).bind()223 // try to throw something inside the arb224 number shouldBeGreaterThan 5225 }226 val assertionError = shouldThrow<AssertionError> { execute(RandomSource.seeded(1234L), throwingArb) }227 assertionError.message shouldBe "4 should be > 5"228 }229 test("should assign edgecases") {230 val edges = setOf("edge1", "edge2")231 val arb = generateArbitrary(edges.toList()) { "abcd" }232 arb.edgecases() shouldContainExactlyInAnyOrder edges233 }234 test("should assign edgecases and shrinker") {235 val shrinker = IntShrinker(1..5)236 val edges = setOf(1, 2)237 val arb = generateArbitrary(edges.toList(), shrinker) { 5 }238 arb.edgecases() shouldContainExactlyInAnyOrder edges239 arb.sample(RandomSource.seeded(1234L)).shrinks.children.value.map { it.value() } shouldBe shrinker.shrink(5)240 }241 test("should use shrinker when provided") {242 val shrinker = IntShrinker(1..5)243 val arb = generateArbitrary(shrinker) { 5 }244 arb.classifier.shouldBeNull()245 val shrinks = arb.sample(RandomSource.seeded(1234L)).shrinks246 shrinks.children.value.map { it.value() } shouldContainExactly shrinker.shrink(5)247 }248 test("should use classifier when provided") {249 val classifier = IntClassifier(1..5)250 val arb = generateArbitrary(classifier) { 5 }251 arb.classifier shouldBeSameInstanceAs classifier252 }253 test("should use classifier and shrinker when provided") {254 val shrinker = IntShrinker(1..5)255 val classifier = IntClassifier(1..5)256 val arb = generateArbitrary(shrinker, classifier) { 5 }257 arb.classifier shouldBeSameInstanceAs classifier258 val shrinks = arb.sample(RandomSource.seeded(1234L)).shrinks259 shrinks.children.value.map { it.value() } shouldContainExactly shrinker.shrink(5)260 }261 test("should use edgecase function when provided") {262 val arb = generateArbitrary({ 5 }) { 10 }263 arb.edgecases() shouldContainExactlyInAnyOrder setOf(5)264 }265 test("should use edgecase function and shrinker when provided") {266 val shrinker = IntShrinker(1..5)267 val arb = generateArbitrary({ 5 }, shrinker) { 10 }268 arb.edgecases() shouldContainExactlyInAnyOrder setOf(5)269 val shrinks = arb.sample(RandomSource.seeded(1234L)).shrinks270 shrinks.children.value.map { it.value() } shouldContainExactly shrinker.shrink(10)271 }272 test("should support .bind() syntax") {273 val arb = Arb.constant(5)274 val shrinker = IntShrinker(1..5)275 val classifier = IntClassifier(1..5)276 generateArbitrary { arb.bind() }.single() shouldBe 5277 generateArbitrary(shrinker) { arb.bind() }.single() shouldBe 5278 generateArbitrary(classifier) { arb.bind() }.single() shouldBe 5279 generateArbitrary(shrinker, classifier) { arb.bind() }.single() shouldBe 5280 generateArbitrary(listOf(5)) { arb.bind() }.single() shouldBe 5281 generateArbitrary({ 5 }) { arb.bind() }.single() shouldBe 5282 generateArbitrary({ 5 }, shrinker) { arb.bind() }.single() shouldBe 5...

Full Screen

Full Screen

bind.kt

Source:bind.kt Github

copy

Full Screen

...432 val arbL = genL.toArb()433 val arbM = genM.toArb()434 val arbN = genN.toArb()435 return object : Arb<T>() {436 override fun edgecase(rs: RandomSource): T? {437 return bindFn(438 arbA.edgecase(rs) ?: arbA.next(rs),439 arbB.edgecase(rs) ?: arbB.next(rs),440 arbC.edgecase(rs) ?: arbC.next(rs),441 arbD.edgecase(rs) ?: arbD.next(rs),442 arbE.edgecase(rs) ?: arbE.next(rs),443 arbF.edgecase(rs) ?: arbF.next(rs),444 arbG.edgecase(rs) ?: arbG.next(rs),445 arbH.edgecase(rs) ?: arbH.next(rs),446 arbI.edgecase(rs) ?: arbI.next(rs),447 arbJ.edgecase(rs) ?: arbJ.next(rs),448 arbK.edgecase(rs) ?: arbK.next(rs),449 arbL.edgecase(rs) ?: arbL.next(rs),450 arbM.edgecase(rs) ?: arbM.next(rs),451 arbN.edgecase(rs) ?: arbN.next(rs),452 )453 }454 override fun sample(rs: RandomSource): Sample<T> {455 val (av, ar) = arbA.sample(rs)456 val (bv, br) = arbB.sample(rs)457 val (cv, cr) = arbC.sample(rs)458 val (dv, dr) = arbD.sample(rs)459 val (ev, er) = arbE.sample(rs)460 val (fv, fr) = arbF.sample(rs)461 val (gv, gr) = arbG.sample(rs)462 val (hv, hr) = arbH.sample(rs)463 val (iv, ir) = arbI.sample(rs)464 val (jv, jr) = arbJ.sample(rs)465 val (kv, kr) = arbK.sample(rs)...

Full Screen

Full Screen

Gen.kt

Source:Gen.kt Github

copy

Full Screen

...23 /**24 * Returns values from this generator as a lazily generated sequence.25 *26 * If this gen is an [Arb], then each value will either be a sample or an edge case. The bias27 * towards edge cases or samples is given by the value of [EdgeConfig.edgecasesGenerationProbability]28 * inside the [edgeConfig] parameter.29 *30 * If this gen is an [Exhaustive], then the returned values will iterate in turn, repeating31 * once exhausted as required.32 *33 */34 fun generate(35 rs: RandomSource,36 edgeConfig: EdgeConfig = EdgeConfig.default()37 ): Sequence<Sample<A>> =38 when (this) {39 is Arb -> {40 val samples = this.samples(rs).iterator()41 generateSequence {42 val isEdgeCase = rs.random.nextDouble(0.0, 1.0) < edgeConfig.edgecasesGenerationProbability43 if (isEdgeCase) {44 this.edgecase(rs)?.asSample() ?: samples.next()45 } else samples.next()46 }47 }48 is Exhaustive -> {49 check(this.values.isNotEmpty()) { "Exhaustive.values shouldn't be a empty list." }50 generateSequence { this.values.map { Sample(it) } }.flatten()51 }52 }53 /**54 * Returns an optional [Classifier] to label values.55 */56 open val classifier: Classifier<out A>? = null57 /**58 * The minimum iteration count required for this [Gen] to be invoked.59 * Requesting a property test with fewer than this will result in an exception.60 */61 fun minIterations(): Int = when (this) {62 is Exhaustive -> this.values.size63 else -> 164 }65}66/**67 * An [Arb] (short for arbitrary) is a generator of values in two categories: edge cases and samples.68 *69 * Edge cases are values that are a common source of bugs. For example, a function using ints is70 * more likely to fail for common edge cases like zero, minus 1, positive 1, [Int.MAX_VALUE] and [Int.MIN_VALUE]71 * rather than random values like 965489. Therefore, it is useful that we try to include such values72 * rather than relying entirely on random values which are unlikely to generate these.73 *74 * Not all arbitraries will utilize edge cases. For example, if you define an integer generator75 * using a subset of the number space - say from 100 to 200 - then no edge cases would be provided.76 *77 * Samples are chosen randomly from the sample space and are used to give a greater breadth to78 * the test cases. For example, in the case of a function using integers, these random values79 * could be from across the entire integer number line, or could be limited to a subset of ints80 * such as natural numbers or even numbers.81 *82 * In addition to values, arbs can optionally implement a [classify] function which classifies83 * the generated values with labels. These labels can then be used to display information on the84 * types of values generated.85 *86 * In order to use an [Arb] outside a property test, one must invoke the [take] method, passing in87 * the number of iterations required and optionally a [ShrinkingMode].88 */89abstract class Arb<out A> : Gen<A>() {90 /**91 * Returns a single edge case for this arbitrary. If this arb supports multiple edge cases,92 * then one should be chosen randomly each time this function is invoked.93 *94 * Can return null if this arb does not provide edge cases.95 */96 abstract fun edgecase(rs: RandomSource): A?97 /**98 * Returns a single random [Sample] from this [Arb] using the supplied random source.99 */100 abstract fun sample(rs: RandomSource): Sample<A>101 /**102 * Returns a sequence from values generated from this arb.103 * Edgecases will be ignored.104 */105 fun samples(rs: RandomSource = RandomSource.default()): Sequence<Sample<A>> {106 return generateSequence { sample(rs) }107 }108 companion object109}110/**111 * An exhaustive is a type of [Gen] which generates an exhaustive set of values from a defined range.112 *113 * An example of a exhaustive is the sequence of integers from 0 to 100.114 * Another example is all strings of two characters.115 *116 * A progression is useful when you want to generate an exhaustive set of values from a given117 * sample space, rather than random values from that space. For example, if you were testing a118 * function that used an enum, you might prefer to guarantee that every enum value is used, rather119 * than selecting randomly from amongst the enum values (with possible duplicates and gaps).120 *121 * Exhaustives do not shrink their values. There is no need to find a smaller failing case, because122 * the smaller values will themselves naturally be included in the tested values.123 *124 * An exhaustive is less suitable when you have a large sample space you need to select values from.125 */126abstract class Exhaustive<out A> : Gen<A>() {127 /**128 * Returns the values of this [Exhaustive].129 */130 abstract val values: List<A>131 /**132 * Converts this into an [Arb] where the generated values of the returned arb133 * are choosen randomly from the values provided by this exhausive.134 */135 fun toArb(): Arb<A> = Arb.of(values)136 companion object137}138fun interface Classifier<A> {139 fun classify(value: A): String?140}141/**142 * Contains a single generated value from a [Gen] and an [RTree] of lazily evaluated shrinks.143 */144data class Sample<out A>(val value: A, val shrinks: RTree<A> = RTree({ value }))145fun <A> A.asSample(): Sample<A> = Sample(this)146/**147 * Returns a [Sample] with shrinks by using the supplied [Shrinker] against the input value [a].148 */149fun <A> sampleOf(a: A, shrinker: Shrinker<A>) = Sample(a, shrinker.rtree(a))150data class EdgeConfig(151 val edgecasesGenerationProbability: Double = PropertyTesting.defaultEdgecasesGenerationProbability152) {153 companion object;154 init {155 check(edgecasesGenerationProbability in 0.0..1.0) {156 "provided edgecasesProbability $edgecasesGenerationProbability is not between 0.0 and 1.0"157 }158 }159}...

Full Screen

Full Screen

combinations.kt

Source:combinations.kt Github

copy

Full Screen

...73 return if (n <= w) e74 else pick(n - w, l.drop(1))75 }76 return arbitrary(77 edgecaseFn = { allArbs.edgecase(it) },78 sampleFn = { rs ->79 val n = rs.random.nextInt(1, total + 1)80 val arb = pick(n, allPairs)81 arb.sample(rs).value82 }83 )84}85/**86 * Generates random permutations of a list.87 */88fun <A> Arb.Companion.shuffle(list: List<A>): Arb<List<A>> = arbitrary {89 list.shuffled(it.random)90}91/**92 * Generates a random subsequence of the input list, including the empty list.93 * The returned list has the same order as the input list.94 */95fun <A> Arb.Companion.subsequence(list: List<A>): Arb<List<A>> = arbitrary {96 val size = it.random.nextInt(0, list.size + 1)97 list.take(size)98}99/**100 * Uses the [Arb]s provided to randomly generate the next element.101 * The returned [Arb]'s edge cases contains the edge cases of the input [Arb]s.102 *103 * The input must be non-empty.104 * The input [Arb]s must be infinite.105 *106 * @return A new [Arb]<A> that will randomly select values from the provided Arbs, and combine all of the provided107 * [Arb]s edge cases108 */109fun <A> Arb.Companion.choice(arb: Arb<A>, vararg arbs: Arb<A>): Arb<A> {110 val arbList = listOf(arb, *arbs)111 return arbitrary(112 edgecaseFn = { arbList.edgecase(it) },113 sampleFn = { arbList.random(it.random).next(it) }114 )115}116/**117 * Uses the [Arb]s provided to randomly generate the next element.118 * The returned [Arb]'s edge cases contains the edge cases of the input [Arb]s.119 * The input [Arb]s must be infinite.120 *121 * @throws IllegalArgumentException if no arbs have been passed to this function122 *123 * @return A new [Arb]<A> that will randomly select values from the provided [Arb]s, and combine all of the provided124 * [Arb]s edge cases125 */126fun <A> Arb.Companion.choice(arbs: List<Arb<A>>): Arb<A> {127 return arbitrary(128 edgecaseFn = { arbs.edgecase(it) },129 sampleFn = { arbs.random(it.random).next(it) }130 )131}...

Full Screen

Full Screen

filter.kt

Source:filter.kt Github

copy

Full Screen

...11 * the predicate.12 */13fun <A> Arb<A>.filter(predicate: (A) -> Boolean): Arb<A> = trampoline { sampleA ->14 object : Arb<A>() {15 override fun edgecase(rs: RandomSource): A? =16 sequenceOf(sampleA.value)17 .plus(generateSequence { this@filter.edgecase(rs) })18 .take(PropertyTesting.maxFilterAttempts)19 .filter(predicate)20 .firstOrNull()21 override fun sample(rs: RandomSource): Sample<A> {22 val sample = sequenceOf(sampleA).plus(this@filter.samples(rs)).filter { predicate(it.value) }.first()23 return Sample(sample.value, sample.shrinks.filter(predicate) ?: RTree({ sample.value }))24 }25 }26}27/**28 * @return a new [Arb] by filtering this arbs output by the negated function [f]29 */30fun <A> Arb<A>.filterNot(f: (A) -> Boolean): Arb<A> = filter { !f(it) }31/**...

Full Screen

Full Screen

edgecase

Using AI Code Generation

copy

Full Screen

1 val edgeCase = Arb.int(0..100).edgecase()2 val edgeCase = Arb.int(0..100).edgecase()3 val edgeCase = Arb.int(0..100).edgecase()4 val edgeCase = Arb.int(0..100).edgecase()5 val edgeCase = Arb.int(0..100).edgecase()6 val edgeCase = Arb.int(0..100).edgecase()7 val edgeCase = Arb.int(0..100).edgecase()8 val edgeCase = Arb.int(0..100).edgecase()9 val edgeCase = Arb.int(0..100).edgecase()10 val edgeCase = Arb.int(0..100).edgecase()11 val edgeCase = Arb.int(0..100).edgecase()12 val edgeCase = Arb.int(0..100).edgecase()13 val edgeCase = Arb.int(0..100).edgecase()14 val edgeCase = Arb.int(0..100).edgecase()

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Kotest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful