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

Best Kotest code snippet using io.kotest.property.arbitrary.edgecases.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

strings.kt

Source:strings.kt Github

copy

Full Screen

...21 val size = rs.random.nextInt(minSize..maxSize)22 codepoints.take(size, rs).joinToString("") { it.asString() }23 }.withEdgecaseFn { rs ->24 if (minSize == maxSize) null else {25 val lowCodePoint = codepoints.edgecase(rs)26 val min = lowCodePoint?.let { cp -> List(minSize) { cp.asString() }.joinToString("") }27 val minPlus1 = lowCodePoint?.let { cp -> List(minSize + 1) { cp.asString() }.joinToString("") }28 val edgeCases = listOfNotNull(min, minPlus1)29 .filter { it.length in minSize..maxSize }30 if (edgeCases.isEmpty()) null else edgeCases.random(rs.random)31 }32 }.withShrinker(StringShrinkerWithMin(minSize))33 .withClassifier(StringClassifier(minSize, maxSize))34 .build()35}36/**37 * Returns an [Arb] where each random value is a String which has a length in the given range.38 * By default the arb uses a [ascii] codepoint generator, but this can be substituted39 * with any codepoint generator. There are many available, such as [katakana] and so on....

Full Screen

Full Screen

CollectionsTest.kt

Source:CollectionsTest.kt Github

copy

Full Screen

...9import io.kotest.matchers.shouldBe10import io.kotest.property.Arb11import io.kotest.property.Exhaustive12import io.kotest.property.arbitrary.double13import io.kotest.property.arbitrary.edgecases14import io.kotest.property.arbitrary.int15import io.kotest.property.arbitrary.list16import io.kotest.property.arbitrary.of17import io.kotest.property.arbitrary.positiveInt18import io.kotest.property.arbitrary.set19import io.kotest.property.arbitrary.single20import io.kotest.property.checkAll21import io.kotest.property.exhaustive.constant22import io.kotest.property.forAll23class CollectionsTest : DescribeSpec({24 describe("Arb.list should") {25 it("not include empty edge cases as first sample") {26 val numGen = Arb.list(Arb.int(), 1..10)27 forAll(1, numGen) { it.isNotEmpty() }28 }29 it("return lists of underlying generators") {30 val gen = Arb.list(Exhaustive.constant(1), 2..10)31 checkAll(gen) {32 it.shouldHaveAtLeastSize(2)33 it.shouldHaveAtMostSize(10)34 it.toSet() shouldBe setOf(1)35 }36 }37 it("include repeated elements in edge cases") {38 val edgeCase = Arb.positiveInt().edgecases().firstOrNull()39 Arb.list(Arb.positiveInt()).edgecases() shouldContain listOf(edgeCase, edgeCase)40 Arb.list(Arb.positiveInt(), 4..6).edgecases() shouldContain listOf(edgeCase, edgeCase, edgeCase, edgeCase)41 }42 it("include empty list in edge cases") {43 Arb.list(Arb.positiveInt()).edgecases() shouldContain emptyList()44 }45 it("respect bounds in edge cases") {46 val edges = Arb.list(Arb.positiveInt(), 2..10).edgecases().toSet()47 edges.forAll { it.shouldNotBeEmpty() }48 }49 it("generate lists of length up to 100 by default") {50 checkAll(10_000, Arb.list(Arb.double())) {51 it.shouldHaveAtMostSize(100)52 }53 }54 it("generate lists in the given range") {55 checkAll(1000, Arb.list(Arb.double(), 250..500)) {56 it.shouldHaveAtLeastSize(250)57 it.shouldHaveAtMostSize(500)58 }59 }60 }...

Full Screen

Full Screen

FilterTest.kt

Source:FilterTest.kt Github

copy

Full Screen

...25 }26 test("should filter edge cases") {27 val arb = Arb.int(1..10).withEdgecases(1, 2, 3).filter { it % 2 == 0 }28 val edgeCases = arb29 .generate(RandomSource.seeded(1234L), EdgeConfig(edgecasesGenerationProbability = 1.0))30 .take(5)31 .map { it.value }32 .toList()33 edgeCases shouldContainExactly listOf(2, 2, 2, 2, 2)34 }35 test("should be stack safe") {36 val arb = object : Arb<Int>() {37 override fun edgecase(rs: RandomSource): Int? = null38 override fun sample(rs: RandomSource): Sample<Int> = Sample(rs.random.nextInt())39 }40 shouldNotThrow<StackOverflowError> {41 arb.filter { it % 2 == 0 }.take(1000000).toList()42 }43 }44 test("should apply filter to shrinks") {45 val arbEvenInts = Arb.int(-100..100).filter { it % 2 == 0 }46 val oddNumbers = (-100..100).filter { it % 2 != 0 }47 arbEvenInts.samples().take(100).forAll { sample ->48 sample.shrinks.value() shouldNotBeIn oddNumbers49 sample.shrinks.children.value.forAll {50 it.value() shouldNotBeIn oddNumbers51 }...

Full Screen

Full Screen

BigDecimalTest.kt

Source:BigDecimalTest.kt Github

copy

Full Screen

...8import io.kotest.matchers.shouldBe9import io.kotest.property.Arb10import io.kotest.property.arbitrary.bigDecimal11import io.kotest.property.arbitrary.bigDecimalDefaultEdgecases12import io.kotest.property.arbitrary.edgecases13import io.kotest.property.arbitrary.take14import java.math.BigDecimal15import java.math.RoundingMode16import java.util.concurrent.TimeUnit17class BigDecimalTest : FunSpec({18 test("Arb.bigDecimal(min, max) should generate bigDecimal between given range") {19 val min = BigDecimal.valueOf(123)20 val max = BigDecimal.valueOf(555)21 Arb.bigDecimal(min, max).take(100).forAll {22 (it >= min && it <= max) shouldBe true23 }24 }25 test("Arb.bigDecimal(scale, rounding) should generate bigDecimal of given scale") {26 Arb.bigDecimal(4, RoundingMode.CEILING).take(100).forAll {27 it.scale() shouldBe 428 }29 }30 test("Arb.bigDecimal(min, max) for large value should complete with in few seconds") {31 shouldCompleteWithin(5, TimeUnit.SECONDS) {32 Arb.bigDecimal(BigDecimal.valueOf(-100_000.00), BigDecimal.valueOf(100_000.00)).take(100).forEach { _ ->33 }34 }35 }36 test("bigDecimalDefaultEdgecases should contain zeros with differing precision") {37 bigDecimalDefaultEdgecases.shouldContain(BigDecimal("0.00"))38 bigDecimalDefaultEdgecases.shouldContain(BigDecimal("0"))39 }40 test("Arb.bigDecimal(min, max) should always contain min as edgecase but not max") {41 val min = BigDecimal.valueOf(123)42 val max = BigDecimal.valueOf(555)43 val actualEdgecases = Arb.bigDecimal(min = min, max = max).edgecases()44 actualEdgecases.shouldContain(min)45 actualEdgecases.shouldNotContain(max)46 }47 test("Arb.bigDecimal(min, max) should only include default edgecases that are in range [min, max)") {48 val min = BigDecimal.valueOf(0)49 val max = BigDecimal.valueOf(5)50 val expectedEdgecases = bigDecimalDefaultEdgecases51 .filter { min <= it && it < max }52 Arb.bigDecimal(min = min, max = max).edgecases().shouldContainAll(expectedEdgecases)53 }54})...

Full Screen

Full Screen

edgecases.kt

Source:edgecases.kt Github

copy

Full Screen

...7 * Randomly chooses an [Arb] and then generates an edge case from that [Arb].8 * If the chosen arb has no edge cases, then another arb will be chosen.9 * If all [Arb]s have no edge cases, then returns null.10 */11tailrec fun <A> List<Arb<A>>.edgecase(rs: RandomSource): A? {12 if (this.isEmpty()) return null13 val shuffled = this.shuffled(rs.random)14 return when (val edge = shuffled.first().edgecase(rs)) {15 null -> this.drop(1).edgecase(rs)16 else -> edge17 }18}19/**20 * Collects the edge cases from this arb.21 * Will stop after the given number of iterations.22 * This function is mainly used for testing.23 */24fun <A> Arb<A>.edgecases(iterations: Int = 100, rs: RandomSource = RandomSource.default()): Set<A> =25 generate(rs, EdgeConfig(edgecasesGenerationProbability = 1.0))26 .take(iterations)27 .map { it.value }28 .toSet()29/**30 * Returns a new [Arb] with the supplied edge cases replacing any existing edge cases.31 */32fun <A> Arb<A>.withEdgecases(edgecases: List<A>): Arb<A> = arbitrary(edgecases) { this@withEdgecases.next(it) }33/**34 * Returns a new [Arb] with the supplied edge cases replacing any existing edge cases.35 */36fun <A> Arb<A>.withEdgecases(vararg edgecases: A): Arb<A> = this.withEdgecases(edgecases.toList())37fun <A> Arb<A>.removeEdgecases(): Arb<A> = this.withEdgecases(emptyList())38/**39 * Returns a new [Arb] with the edge cases from this arb transformed by the given function [f].40 */41fun <A> Arb<A>.modifyEdgecases(f: (A) -> A?): Arb<A> = object : Arb<A>() {42 override fun edgecase(rs: RandomSource): A? = this@modifyEdgecases.edgecase(rs)?.let(f)43 override fun sample(rs: RandomSource): Sample<A> = this@modifyEdgecases.sample(rs)44}...

Full Screen

Full Screen

merge.kt

Source:merge.kt Github

copy

Full Screen

...19 * @return the merged arg.20 */21fun <A, B : A> Arb<A>.merge(other: Gen<B>): Arb<A> = trampoline { sampleA ->22 object : Arb<A>() {23 override fun edgecase(rs: RandomSource): A? = when (other) {24 is Arb -> if (rs.random.nextBoolean()) sampleA.value else other.edgecase(rs)25 is Exhaustive -> sampleA.value26 }27 override fun sample(rs: RandomSource): Sample<A> =28 if (rs.random.nextBoolean()) {29 sampleA30 } else {31 when (other) {32 is Arb -> other.sample(rs)33 is Exhaustive -> other.toArb().sample(rs)34 }35 }36 }37}...

Full Screen

Full Screen

edgecase

Using AI Code Generation

copy

Full Screen

1"EdgeCase" should {2"return a list of edge cases" {3val edgeCases = edgecases(1, 2, 3, 4, 5)4edgeCases.toList() shouldBe listOf(1, 2, 3, 4, 5)5}6"return a list of edge cases for strings" {7val edgeCases = edgecases("a", "b", "c")8edgeCases.toList() shouldBe listOf("a", "b", "c")9}10"return a list of edge cases for chars" {11val edgeCases = edgecases('a', 'b', 'c')12edgeCases.toList() shouldBe listOf('a', 'b', 'c')13}14"return a list of edge cases for booleans" {15val edgeCases = edgecases(true, false)16edgeCases.toList() shouldBe listOf(true, false)17}18"return a list of edge cases for floats" {19val edgeCases = edgecases(1.0f, 2.0f, 3.0f, 4.0f, 5.0f)20edgeCases.toList() shouldBe listOf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f)21}22"return a list of edge cases for longs" {23val edgeCases = edgecases(1L, 2L, 3L, 4L, 5L)24edgeCases.toList() shouldBe listOf(1L, 2L, 3L, 4L, 5L)25}26"return a list of edge cases for doubles" {27val edgeCases = edgecases(1.0, 2.0, 3.0, 4.0, 5.0)28edgeCases.toList() shouldBe listOf(1.0, 2.0, 3.0, 4.0, 5.0)29}30"return a list of edge cases for bytes" {31val edgeCases = edgecases(1.toByte(), 2.toByte(), 3.toByte(), 4.toByte(), 5.toByte())32edgeCases.toList() shouldBe listOf(1.toByte(), 2.toByte(), 3.toByte(), 4.toByte(), 5.toByte())33}34"return a list of edge cases for shorts" {35val edgeCases = edgecases(1.to

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