How to use locale class of io.kotest.property.arbitrary package

Best Kotest code snippet using io.kotest.property.arbitrary.locale

FeatureFlagGeneratorSpec.kt

Source:FeatureFlagGeneratorSpec.kt Github

copy

Full Screen

1package io.mehow.laboratory.generator2import com.squareup.kotlinpoet.ClassName3import io.kotest.assertions.throwables.shouldThrow4import io.kotest.core.spec.style.DescribeSpec5import io.kotest.matchers.throwable.shouldHaveMessage6import io.kotest.property.Arb7import io.kotest.property.arbitrary.stringPattern8import io.kotest.property.checkAll9import io.mehow.laboratory.generator.Visibility.Internal10import io.mehow.laboratory.generator.Visibility.Public11import io.mehow.laboratory.generator.test.shouldSpecify12import java.util.Locale13import kotlin.DeprecationLevel.ERROR14import kotlin.DeprecationLevel.HIDDEN15import kotlin.DeprecationLevel.WARNING16internal class FeatureFlagGeneratorSpec : DescribeSpec({17 describe("feature flag model") {18 context("options") {19 it("cannot be empty") {20 val exception = shouldThrow<IllegalArgumentException> {21 FeatureFlagModel(22 ClassName("io.mehow", "FeatureA"),23 options = emptyList(),24 )25 }26 exception shouldHaveMessage "io.mehow.FeatureA must have at least one option"27 }28 }29 context("default") {30 it("cannot have no options") {31 checkAll(32 Arb.stringPattern("[a-z](0)([a-z]{0,10})"),33 Arb.stringPattern("[a-z](1)([a-z]{0,10})"),34 ) { first, second ->35 val exception = shouldThrow<IllegalArgumentException> {36 FeatureFlagModel(37 ClassName("io.mehow", "FeatureA"),38 listOf(FeatureFlagOption(first), FeatureFlagOption(second)),39 )40 }41 exception shouldHaveMessage "io.mehow.FeatureA must have exactly one default option"42 }43 }44 it("cannot have multiple options") {45 checkAll(46 Arb.stringPattern("[a-z](0)([a-z]{0,10})"),47 Arb.stringPattern("[a-z](1)([a-z]{0,10})"),48 Arb.stringPattern("[a-z](2)([a-z]{0,10})"),49 ) { first, second, third ->50 val exception = shouldThrow<IllegalArgumentException> {51 FeatureFlagModel(52 ClassName("io.mehow", "FeatureA"),53 listOf(54 FeatureFlagOption(first, isDefault = true),55 FeatureFlagOption(second),56 FeatureFlagOption(third, isDefault = true),57 ),58 )59 }60 exception shouldHaveMessage "io.mehow.FeatureA must have exactly one default option"61 }62 }63 }64 context("supervisor option") {65 it("cannot supervise itself") {66 val model = FeatureFlagModel(67 ClassName("io.mehow", "FeatureA"),68 listOf(FeatureFlagOption("First", isDefault = true)),69 )70 val exception = shouldThrow<IllegalArgumentException> {71 FeatureFlagModel(72 model.className,73 model.options,74 supervisor = Supervisor(model, model.options.first()),75 )76 }77 exception shouldHaveMessage "io.mehow.FeatureA cannot supervise itself"78 }79 }80 }81 describe("generated feature flag") {82 it("can be internal") {83 val model = FeatureFlagModel(84 ClassName("io.mehow", "FeatureA"),85 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),86 visibility = Internal,87 )88 val fileSpec = model.prepare()89 fileSpec shouldSpecify """90 |package io.mehow91 |92 |import io.mehow.laboratory.Feature93 |94 |internal enum class FeatureA : Feature<FeatureA> {95 | First,96 | Second,97 | ;98 |99 | public override val defaultOption: FeatureA100 | get() = First101 |}102 |103 """.trimMargin()104 }105 it("can be public") {106 val model = FeatureFlagModel(107 ClassName("io.mehow", "FeatureA"),108 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),109 visibility = Public,110 )111 val fileSpec = model.prepare()112 fileSpec shouldSpecify """113 |package io.mehow114 |115 |import io.mehow.laboratory.Feature116 |117 |public enum class FeatureA : Feature<FeatureA> {118 | First,119 | Second,120 | ;121 |122 | public override val defaultOption: FeatureA123 | get() = First124 |}125 |126 """.trimMargin()127 }128 it("can have single option") {129 val model = FeatureFlagModel(130 ClassName("io.mehow", "FeatureA"),131 listOf(FeatureFlagOption("First", isDefault = true)),132 )133 val fileSpec = model.prepare()134 fileSpec shouldSpecify """135 |package io.mehow136 |137 |import io.mehow.laboratory.Feature138 |139 |public enum class FeatureA : Feature<FeatureA> {140 | First,141 | ;142 |143 | public override val defaultOption: FeatureA144 | get() = First145 |}146 |147 """.trimMargin()148 }149 it("can have source") {150 val model = FeatureFlagModel(151 ClassName("io.mehow", "FeatureA"),152 options = listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),153 sourceOptions = listOf(FeatureFlagOption("Remote")),154 )155 val fileSpec = model.prepare()156 fileSpec shouldSpecify """157 |package io.mehow158 |159 |import io.mehow.laboratory.Feature160 |import java.lang.Class161 |162 |public enum class FeatureA : Feature<FeatureA> {163 | First,164 | Second,165 | ;166 |167 | public override val defaultOption: FeatureA168 | get() = First169 |170 | public override val source: Class<out Feature<*>> = Source::class.java171 |172 | public enum class Source : Feature<Source> {173 | Local,174 | Remote,175 | ;176 |177 | public override val defaultOption: Source178 | get() = Local179 | }180 |}181 |182 """.trimMargin()183 }184 it("does not have source parameter if only source is Local") {185 val model = FeatureFlagModel(186 ClassName("io.mehow", "FeatureA"),187 options = listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),188 sourceOptions = listOf(FeatureFlagOption("Local")),189 )190 val fileSpec = model.prepare()191 fileSpec shouldSpecify """192 |package io.mehow193 |194 |import io.mehow.laboratory.Feature195 |196 |public enum class FeatureA : Feature<FeatureA> {197 | First,198 | Second,199 | ;200 |201 | public override val defaultOption: FeatureA202 | get() = First203 |}204 |205 """.trimMargin()206 }207 it("filters out any custom local source") {208 val localPermutations = (0b00000..0b11111).map {209 listOf(it and 0b00001, it and 0b00010, it and 0b00100, it and 0b01000, it and 0b10000)210 .map { mask -> mask != 0 }211 .mapIndexed { index, mask ->212 val chars = "local"[index].toString()213 if (mask) chars else chars.replaceFirstChar { char -> char.titlecase(Locale.ROOT) }214 }.joinToString(separator = "")215 }216 val model = FeatureFlagModel(217 ClassName("io.mehow", "FeatureA"),218 options = listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),219 sourceOptions = (localPermutations + "Remote").map(::FeatureFlagOption),220 )221 val fileSpec = model.prepare()222 fileSpec shouldSpecify """223 |package io.mehow224 |225 |import io.mehow.laboratory.Feature226 |import java.lang.Class227 |228 |public enum class FeatureA : Feature<FeatureA> {229 | First,230 | Second,231 | ;232 |233 | public override val defaultOption: FeatureA234 | get() = First235 |236 | public override val source: Class<out Feature<*>> = Source::class.java237 |238 | public enum class Source : Feature<Source> {239 | Local,240 | Remote,241 | ;242 |243 | public override val defaultOption: Source244 | get() = Local245 | }246 |}247 |248 """.trimMargin()249 }250 it("can change default source") {251 val model = FeatureFlagModel(252 ClassName("io.mehow", "FeatureA"),253 options = listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),254 sourceOptions = listOf(FeatureFlagOption("Remote", isDefault = true)),255 )256 val fileSpec = model.prepare()257 fileSpec shouldSpecify """258 |package io.mehow259 |260 |import io.mehow.laboratory.Feature261 |import java.lang.Class262 |263 |public enum class FeatureA : Feature<FeatureA> {264 | First,265 | Second,266 | ;267 |268 | public override val defaultOption: FeatureA269 | get() = First270 |271 | public override val source: Class<out Feature<*>> = Source::class.java272 |273 | public enum class Source : Feature<Source> {274 | Local,275 | Remote,276 | ;277 |278 | public override val defaultOption: Source279 | get() = Remote280 | }281 |}282 |283 """.trimMargin()284 }285 it("source visibility follows feature visibility") {286 val model = FeatureFlagModel(287 ClassName("io.mehow", "FeatureA"),288 options = listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),289 visibility = Internal,290 sourceOptions = listOf(FeatureFlagOption("Remote")),291 )292 val fileSpec = model.prepare()293 fileSpec shouldSpecify """294 |package io.mehow295 |296 |import io.mehow.laboratory.Feature297 |import java.lang.Class298 |299 |internal enum class FeatureA : Feature<FeatureA> {300 | First,301 | Second,302 | ;303 |304 | public override val defaultOption: FeatureA305 | get() = First306 |307 | public override val source: Class<out Feature<*>> = Source::class.java308 |309 | internal enum class Source : Feature<Source> {310 | Local,311 | Remote,312 | ;313 |314 | public override val defaultOption: Source315 | get() = Local316 | }317 |}318 |319 """.trimMargin()320 }321 context("description") {322 it("is added as KDoc") {323 val model = FeatureFlagModel(324 ClassName("io.mehow", "FeatureA"),325 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),326 description = "Feature description",327 )328 val fileSpec = model.prepare()329 fileSpec shouldSpecify """330 |package io.mehow331 |332 |import io.mehow.laboratory.Feature333 |import kotlin.String334 |335 |/**336 | * Feature description337 | */338 |public enum class FeatureA : Feature<FeatureA> {339 | First,340 | Second,341 | ;342 |343 | public override val defaultOption: FeatureA344 | get() = First345 |346 | public override val description: String = "Feature description"347 |}348 |349 """.trimMargin()350 }351 it("does not break hyperlinks") {352 val model = FeatureFlagModel(353 ClassName("io.mehow", "FeatureA"),354 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),355 description = "Some [long hyperlink](https://square.github.io/kotlinpoet/1.x/kotlinpoet-classinspector-elements/com.squareup.kotlinpoet.classinspector.elements/) in the KDoc.",356 )357 val fileSpec = model.prepare()358 fileSpec shouldSpecify """359 |package io.mehow360 |361 |import io.mehow.laboratory.Feature362 |import kotlin.String363 |364 |/**365 | * Some366 | * [long hyperlink](https://square.github.io/kotlinpoet/1.x/kotlinpoet-classinspector-elements/com.squareup.kotlinpoet.classinspector.elements/)367 | * in the KDoc.368 | */369 |public enum class FeatureA : Feature<FeatureA> {370 | First,371 | Second,372 | ;373 |374 | public override val defaultOption: FeatureA375 | get() = First376 |377 | public override val description: String =378 | "Some [long hyperlink](https://square.github.io/kotlinpoet/1.x/kotlinpoet-classinspector-elements/com.squareup.kotlinpoet.classinspector.elements/) in the KDoc."379 |}380 |381 """.trimMargin()382 }383 }384 context("can be deprecated") {385 it("with warning level by default") {386 val model = FeatureFlagModel(387 ClassName("io.mehow", "FeatureA"),388 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),389 deprecation = Deprecation("Deprecation message"),390 )391 val fileSpec = model.prepare()392 fileSpec shouldSpecify """393 |package io.mehow394 |395 |import io.mehow.laboratory.Feature396 |import kotlin.Deprecated397 |import kotlin.DeprecationLevel398 |import kotlin.Suppress399 |400 |@Deprecated(401 | message = "Deprecation message",402 | level = DeprecationLevel.WARNING403 |)404 |public enum class FeatureA : Feature<@Suppress("DEPRECATION") FeatureA> {405 | First,406 | Second,407 | ;408 |409 | @Suppress("DEPRECATION")410 | public override val defaultOption: FeatureA411 | get() = First412 |}413 |414 """.trimMargin()415 }416 enumValues<DeprecationLevel>().forEach { level ->417 it("with explicit $level deprecation level") {418 val model = FeatureFlagModel(419 ClassName("io.mehow", "FeatureA"),420 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),421 deprecation = Deprecation("Deprecation message", level),422 )423 val suppressLevel = when (level) {424 WARNING -> "DEPRECATION"425 ERROR, HIDDEN -> "DEPRECATION_ERROR"426 }427 val fileSpec = model.prepare()428 fileSpec shouldSpecify """429 |package io.mehow430 |431 |import io.mehow.laboratory.Feature432 |import kotlin.Deprecated433 |import kotlin.DeprecationLevel434 |import kotlin.Suppress435 |436 |@Deprecated(437 | message = "Deprecation message",438 | level = DeprecationLevel.${level}439 |)440 |public enum class FeatureA : Feature<@Suppress("$suppressLevel") FeatureA> {441 | First,442 | Second,443 | ;444 |445 | @Suppress("$suppressLevel")446 | public override val defaultOption: FeatureA447 | get() = First448 |}449 |450 """.trimMargin()451 }452 }453 }454 it("can have supervisor") {455 val supervisor = FeatureFlagModel(456 ClassName("io.mehow.supervisor", "Supervisor"),457 listOf(FeatureFlagOption("First", isDefault = true)),458 )459 val model = FeatureFlagModel(460 ClassName("io.mehow", "FeatureA"),461 listOf(FeatureFlagOption("First", isDefault = true), FeatureFlagOption("Second")),462 supervisor = Supervisor(supervisor, supervisor.options.first()),463 )464 val fileSpec = model.prepare()465 fileSpec shouldSpecify """466 |package io.mehow467 |468 |import io.mehow.laboratory.Feature469 |import io.mehow.supervisor.Supervisor470 |471 |public enum class FeatureA : Feature<FeatureA> {472 | First,473 | Second,474 | ;475 |476 | public override val defaultOption: FeatureA477 | get() = First478 |479 | public override val supervisorOption: Feature<*> = Supervisor.First480 |}481 |482 """.trimMargin()483 }484 }485})...

Full Screen

Full Screen

NodeGen.kt

Source:NodeGen.kt Github

copy

Full Screen

1package ru.dimsuz.way.generator2import io.kotest.property.Arb3import io.kotest.property.Shrinker4import io.kotest.property.arbitrary.ListShrinker5import io.kotest.property.arbitrary.arbitrary6import io.kotest.property.arbitrary.az7import io.kotest.property.arbitrary.element8import io.kotest.property.arbitrary.map9import io.kotest.property.arbitrary.next10import io.kotest.property.arbitrary.single11import io.kotest.property.arbitrary.string12import io.kotest.property.arbitrary.take13import ru.dimsuz.way.Event14import ru.dimsuz.way.NodeKey15import ru.dimsuz.way.entity.NodeScheme16import ru.dimsuz.way.entity.SchemeNode17import ru.dimsuz.way.entity.fold18import java.util.Locale19import kotlin.random.nextInt20fun Arb.Companion.scheme(maxLevel: Int = 2): Arb<NodeScheme> {21 return arbitrary(shrinker = SchemeShrinker()) { rs ->22 val nodes = Arb.schemeNodes(maxLevel).next(rs)23 NodeScheme(24 initial = Arb.element(nodes.keys).next(rs),25 nodes = nodes26 )27 }28}29fun Arb.Companion.schemeWithEventSequence(maxLevel: Int = 2): Arb<Pair<NodeScheme, List<Event>>> {30 return arbitrary(shrinker = SchemeWithEventShrinker()) { rs ->31 val scheme = Arb.scheme(maxLevel).single(rs)32 val eventSequence = Arb.eventSequence(scheme).single(rs)33 scheme to eventSequence34 }35}36private class SchemeWithEventShrinker : Shrinker<Pair<NodeScheme, List<Event>>> {37 private val eventShrinker = ListShrinker<Event>(GEN_EVENTS_MIN..GEN_EVENTS_MAX)38 override fun shrink(value: Pair<NodeScheme, List<Event>>): List<Pair<NodeScheme, List<Event>>> {39 val events = value.second40 val scheme = value.first41 return listOf(42 scheme.filterNodesWithEvents(events, scheme.findNodesTargetedByEvents(events)) to events43 ).plus(44 eventShrinker.shrink(events).map {45 scheme.filterNodesWithEvents(it, scheme.findNodesTargetedByEvents(it)) to it46 }47 )48 }49 private fun NodeScheme.findNodesTargetedByEvents(events: List<Event>): List<String> {50 return this.fold { schemeNode, states ->51 val s = when (schemeNode) {52 is SchemeNode.Atomic -> {53 schemeNode.transitions.filterKeys { events.any { e -> e.name == it } }.map { it.value.key }54 }55 is SchemeNode.Compound -> emptyList()56 }57 states.plusElement(s).flatten()58 }59 }60 // TODO rewrite this at least to be extension on SchemeNode.Compound (wrap root NodeScheme in it)61 // or using fold62 private fun NodeScheme.filterNodesWithEvents(events: List<Event>, targets: List<String>): NodeScheme {63 if (events.isEmpty()) return this64 // TODO also filter unneeded transitions65 return NodeScheme(66 initial = initial,67 nodes = this.nodes.entries.mapNotNull { (key, node) ->68 when (node) {69 is SchemeNode.Atomic -> {70 val transitions = node.transitions.filter { (event, _) -> events.any { it.name == event } }71 if (transitions.isNotEmpty() || targets.contains(key))72 key to node.copy(transitions = transitions) else null73 }74 is SchemeNode.Compound -> {75 val mappedNodes = node.scheme.filterNodesWithEvents(events, targets).nodes.toMutableMap()76 if (mappedNodes.isNotEmpty() || targets.contains(key)) {77 if (!mappedNodes.containsKey(node.scheme.initial)) {78 // if initial was filtered out, add it back it's required79 mappedNodes[node.scheme.initial] = node.scheme.nodes[node.scheme.initial]!!80 }81 key to SchemeNode.Compound(NodeScheme(node.scheme.initial, mappedNodes))82 } else null83 }84 }85 }86 .toMap()87 .let { if (it.isNotEmpty() && !it.containsKey(initial)) it.plus(initial to this.nodes[initial]!!) else it }88 )89 }90}91/**92 * Generates a sequence of events which represent a valid set of transitions.93 * Events are selected so that each of them will be valid for the node which is reached94 * by sending a sequence of events preceding the current one.95 * That implies that each event will transition to a new node, never staying on the same one.96 */97fun Arb.Companion.eventSequence(scheme: NodeScheme): Arb<List<Event>> {98 return arbitrary(shrinker = ListShrinker(GEN_EVENTS_MIN..GEN_EVENTS_MAX)) { rs ->99 val count = rs.random.nextInt(GEN_EVENTS_MIN..GEN_EVENTS_MAX)100 val events = mutableListOf<Event>()101 var containingNode = SchemeNode.Compound(scheme)102 var currentNode = scheme.nodes[scheme.initial]103 while (events.size < count) {104 when (currentNode) {105 is SchemeNode.Atomic -> {106 if (currentNode.transitions.isEmpty()) {107 break108 }109 val transition = Arb.element(currentNode.transitions.entries).next(rs)110 events.add(Event(name = transition.key))111 currentNode = containingNode.scheme.nodes[transition.value.key]112 ?: error("failed to find node '${transition.value.key}' in the containing node")113 }114 is SchemeNode.Compound -> {115 containingNode = currentNode116 currentNode = currentNode.scheme.nodes[currentNode.scheme.initial]117 ?: error("no initial node definition found for '${currentNode.scheme.initial}'")118 }119 }120 }121 events122 }123}124private fun Arb.Companion.schemeNodes(maxLevel: Int): Arb<Map<String, SchemeNode>> {125 return arbitrary { rs ->126 val nodeKeys = Arb.nodeKeyName().take(rs.random.nextInt(1..30), rs).toList()127 val atomicNodes = mutableMapOf<String, NodeTransitions>()128 val compoundNodeKeys = if (maxLevel > 0 && nodeKeys.size >= 3) {129 nodeKeys.take(rs.random.nextInt(0, nodeKeys.size / 3))130 } else emptyList()131 val atomicNodeKeys = nodeKeys.minus(compoundNodeKeys)132 atomicNodeKeys.forEach { nodeKey ->133 if (ENABLE_SCHEME_GEN_DEBUG) {134 println("generating transitions for node $nodeKey")135 }136 // better have more states than events, otherwise it would be hard to137 // find a combination of transitions which doesn't introduce a cycle138 val events = Arb.eventName().take(rs.random.nextInt(0..nodeKeys.size / 2), rs)139 val potentialTargets = nodeKeys.minus(nodeKey)140 val transitions = mutableMapOf<String, String>()141 var attemptsRemaining = 15142 for (event in events) {143 while (attemptsRemaining > 0) {144 val target = potentialTargets.random(rs.random)145 transitions[event] = target146 if (hasCycle(atomicNodes, nodeKey, transitions)) {147 transitions.remove(event)148 attemptsRemaining -= 1149 } else break150 }151 if (attemptsRemaining <= 0) {152 if (ENABLE_SCHEME_GEN_DEBUG) {153 println("attempts exhausted while trying to find non-cycling targets for node $nodeKey, moving on")154 }155 break156 }157 }158 atomicNodes[nodeKey] = transitions159 }160 val scheme = HashMap<String, SchemeNode>(atomicNodes.size + compoundNodeKeys.size)161 atomicNodes.forEach { (key, transitions) ->162 scheme[key] = SchemeNode.Atomic(transitions.entries.associate { Event.Name(it.key) to NodeKey(it.value) })163 }164 compoundNodeKeys.forEach { key ->165 scheme[key] = SchemeNode.Compound(Arb.scheme(maxLevel - 1).next(rs))166 }167 scheme168 }169}170typealias NodeTransitions = Map<String, String>171private fun hasCycle(nodes: Map<String, NodeTransitions>, newKey: String, newKeyTransitions: NodeTransitions): Boolean {172 val adjacent = HashMap<String, Collection<String>>(nodes.size + 1)173 nodes.forEach { (s, map) -> adjacent[s] = map.values }174 adjacent[newKey] = newKeyTransitions.values175 val cycle = dfsCycleSearch(adjacent)176 return if (cycle != null) {177 if (ENABLE_SCHEME_GEN_DEBUG) {178 println("cycle detected in nodes ${cycle.first} → ${cycle.second}")179 }180 true181 } else false182}183private fun dfsCycleSearch(adjacent: Map<String, Collection<String>>): Pair<String, String>? {184 val discovered = HashSet<String>(adjacent.size)185 val finished = HashSet<String>(adjacent.size)186 fun dfsVisit(key: String): Pair<String, String>? {187 discovered.add(key)188 adjacent[key].orEmpty().forEach { key1 ->189 if (key1 in discovered) {190 return key to key1191 }192 if (key1 !in finished) {193 dfsVisit(key1)194 }195 }196 discovered.remove(key)197 finished.add(key)198 return null199 }200 adjacent.keys.forEach { key ->201 if (key !in discovered && key !in finished) {202 val cycle = dfsVisit(key)203 if (cycle != null) {204 return cycle205 }206 }207 }208 return null209}210private fun Arb.Companion.nodeKeyName() = Arb.string(5..8, Arb.az())211private fun Arb.Companion.eventName() = Arb.string(5..8, Arb.az()).map { it.uppercase(Locale.getDefault()) }212fun Arb.Companion.nodeKey(): Arb<NodeKey> {213 return Arb.nodeKeyName().map { NodeKey(it) }214}215fun Arb.Companion.event(): Arb<Event> {216 return Arb.eventName().map { Event(Event.Name(it)) }217}218private class SchemeShrinker : Shrinker<NodeScheme> {219 override fun shrink(value: NodeScheme): List<NodeScheme> {220 return when {221 value.nodes.isEmpty() -> emptyList()222 value.nodes.size == 1 -> emptyList()223 else -> {224 listOfNotNull(225 // only the initial226 value.nodes.filter { it.key == value.initial },227 // first non-initial dropped228 value.nodes.minus(value.nodes.keys.first { it != value.initial }),229 // last non-initial dropped230 value.nodes.minus(value.nodes.keys.last { it != value.initial }),231 // half of the nodes232 value.nodes.minus(value.nodes.keys.toList().filter { it != value.initial }.dropLast(value.nodes.size / 2)),233 ).map { NodeScheme(value.initial, it) }234 }235 }236 }237}238private const val ENABLE_SCHEME_GEN_DEBUG = false239private const val GEN_EVENTS_MIN = 1240private const val GEN_EVENTS_MAX = 50...

Full Screen

Full Screen

locale.kt

Source:locale.kt Github

copy

Full Screen

1package io.kotest.property.arbitrary2import io.kotest.property.Arb3// this is a dump of some locales built into the java.util.Locale class on JDK11, executed on a linux ubuntu os4val locales = listOf(5 "af",6 "af_NA",7 "af_ZA",8 "agq",9 "agq_CM",10 "ak",11 "ak_GH",12 "am",13 "am_ET",14 "ar",15 "ar_001",16 "ar_AE",17 "ar_BH",18 "ar_DJ",19 "ar_DZ",20 "ar_EG",21 "ar_EH",22 "ar_ER",23 "ar_IL",24 "ar_IQ",25 "ar_JO",26 "ar_KM",27 "ar_KW",28 "ar_LB",29 "ar_LY",30 "ar_MA",31 "ar_MR",32 "ar_OM",33 "ar_PS",34 "ar_QA",35 "ar_SA",36 "ar_SD",37 "ar_SO",38 "ar_SS",39 "ar_SY",40 "ar_TD",41 "ar_TN",42 "ar_YE",43 "as",44 "as_IN",45 "asa",46 "asa_TZ",47 "ast",48 "ast_ES",49 "az",50 "bas",51 "bas_CM",52 "be",53 "be_BY",54 "bem",55 "bem_ZM",56 "bez",57 "bez_TZ",58 "bg",59 "bg_BG",60 "bm",61 "bm_ML",62 "bn",63 "bn_BD",64 "bn_IN",65 "bo",66 "bo_CN",67 "bo_IN",68 "br",69 "br_FR",70 "brx",71 "brx_IN",72 "bs",73 "ca",74 "ca_AD",75 "ca_ES",76 "ca_ES_VALENCIA",77 "ca_FR",78 "ca_IT",79 "ccp",80 "ccp_BD",81 "ccp_IN",82 "ce",83 "ce_RU",84 "cgg",85 "cgg_UG",86 "chr",87 "chr_US",88 "ckb",89 "ckb_IQ",90 "ckb_IR",91 "cs",92 "cs_CZ",93 "cu",94 "cu_RU",95 "cy",96 "cy_GB",97 "da",98 "da_DK",99 "da_GL",100 "dav",101 "dav_KE",102 "de",103 "de_AT",104 "de_BE",105 "de_CH",106 "de_DE",107 "de_IT",108 "de_LI",109 "de_LU",110 "dje",111 "dje_NE",112 "dsb",113 "dsb_DE",114 "dua",115 "dua_CM",116 "dyo",117 "dyo_SN",118 "dz",119 "dz_BT",120 "ebu",121 "ebu_KE",122 "ee",123 "ee_GH",124 "ee_TG",125 "el",126 "el_CY",127 "el_GR",128 "en",129 "en_001",130 "en_150",131 "en_AG",132 "en_AI",133 "en_AS",134 "en_AT",135 "en_AU",136 "en_BB",137 "en_BE",138 "en_BI",139 "en_BM",140 "en_BS",141 "en_BW",142 "en_BZ",143 "en_CA",144 "en_CC",145 "en_CH",146 "en_CK",147 "en_CM",148 "en_CX",149 "en_CY",150 "en_DE",151 "en_DG",152 "en_DK",153 "en_DM",154 "en_ER",155 "en_FI",156 "en_FJ",157 "en_FK",158 "en_FM",159 "en_GB",160 "en_GD",161 "en_GG",162 "en_GH",163 "en_GI",164 "en_GM",165 "en_GU",166 "en_GY",167 "en_HK",168 "en_IE",169 "en_IL",170 "en_IM",171 "en_IN",172 "en_IO",173 "en_JE",174 "en_JM",175 "en_KE",176 "en_KI",177 "en_KN",178 "en_KY",179 "en_LC",180 "en_LR",181 "en_LS",182 "en_MG",183 "en_MH",184 "en_MO",185 "en_MP",186 "en_MS",187 "en_MT",188 "en_MU",189 "en_MW",190 "en_MY",191 "en_NA",192 "en_NF",193 "en_NG",194 "en_NL",195 "en_NR",196 "en_NU",197 "en_NZ",198 "en_PG",199 "en_PH",200 "en_PK",201 "en_PN",202 "en_PR",203 "en_PW",204 "en_RW",205 "en_SB",206 "en_SC",207 "en_SD",208 "en_SE",209 "en_SG",210 "en_SH",211 "en_SI",212 "en_SL",213 "en_SS",214 "en_SX",215 "en_SZ",216 "en_TC",217 "en_TK",218 "en_TO",219 "en_TT",220 "en_TV",221 "en_TZ",222 "en_UG",223 "en_UM",224 "en_US",225 "en_US_POSIX",226 "en_VC",227 "en_VG",228 "en_VI",229 "en_VU",230 "en_WS",231 "en_ZA",232 "en_ZM",233 "en_ZW",234 "eo",235 "eo_001",236 "es",237 "es_419",238 "es_AR",239 "es_BO",240 "es_BR",241 "es_BZ",242 "es_CL",243 "es_CO",244 "es_CR",245 "es_CU",246 "es_DO",247 "es_EA",248 "es_EC",249 "es_ES",250 "es_GQ",251 "es_GT",252 "es_HN",253 "es_IC",254 "es_MX",255 "es_NI",256 "es_PA",257 "es_PE",258 "es_PH",259 "es_PR",260 "es_PY",261 "es_SV",262 "es_US",263 "es_UY",264 "es_VE",265 "et",266 "et_EE",267 "eu",268 "eu_ES",269 "ewo",270 "ewo_CM",271 "fa",272 "fa_AF",273 "fa_IR",274 "ff",275 "ff_CM",276 "ff_GN",277 "ff_MR",278 "ff_SN",279 "fi",280 "fi_FI",281 "fil",282 "fil_PH",283 "fo",284 "fo_DK",285 "fo_FO",286 "fr",287 "fr_BE",288 "fr_BF",289 "fr_BI",290 "fr_BJ",291 "fr_BL",292 "fr_CA",293 "fr_CD",294 "fr_CF",295 "fr_CG",296 "fr_CH",297 "fr_CI",298 "fr_CM",299 "fr_DJ",300 "fr_DZ",301 "fr_FR",302 "fr_GA",303 "fr_GF",304 "fr_GN",305 "fr_GP",306 "fr_GQ",307 "fr_HT",308 "fr_KM",309 "fr_LU",310 "fr_MA",311 "fr_MC",312 "fr_MF",313 "fr_MG",314 "fr_ML",315 "fr_MQ",316 "fr_MR",317 "fr_MU",318 "fr_NC",319 "fr_NE",320 "fr_PF",321 "fr_PM",322 "fr_RE",323 "fr_RW",324 "fr_SC",325 "fr_SN",326 "fr_SY",327 "fr_TD",328 "fr_TG",329 "fr_TN",330 "fr_VU",331 "fr_WF",332 "fr_YT",333 "fur",334 "fur_IT",335 "fy",336 "fy_NL",337 "ga",338 "ga_IE",339 "gd",340 "gd_GB",341 "gl",342 "gl_ES",343 "gsw",344 "gsw_CH",345 "gsw_FR",346 "gsw_LI",347 "gu",348 "gu_IN",349 "guz",350 "guz_KE",351 "gv",352 "gv_IM",353 "ha",354 "ha_GH",355 "ha_NE",356 "ha_NG",357 "haw",358 "haw_US",359 "hi",360 "hi_IN",361 "hr",362 "hr_BA",363 "hr_HR",364 "hsb",365 "hsb_DE",366 "hu",367 "hu_HU",368 "hy",369 "hy_AM",370 "ig",371 "ig_NG",372 "ii",373 "ii_CN",374 "in",375 "in_ID",376 "is",377 "is_IS",378 "it",379 "it_CH",380 "it_IT",381 "it_SM",382 "it_VA",383 "iw",384 "iw_IL",385 "ja",386 "ja_JP",387 "jgo",388 "jgo_CM",389 "ji",390 "ji_001",391 "jmc",392 "jmc_TZ",393 "ka",394 "ka_GE",395 "kab",396 "kab_DZ",397 "kam",398 "kam_KE",399 "kde",400 "kde_TZ",401 "kea",402 "kea_CV",403 "khq",404 "khq_ML",405 "ki",406 "ki_KE",407 "kk",408 "kk_KZ",409 "kkj",410 "kkj_CM",411 "kl",412 "kl_GL",413 "kln",414 "kln_KE",415 "km",416 "km_KH",417 "kn",418 "kn_IN",419 "ko",420 "ko_KP",421 "ko_KR",422 "kok",423 "kok_IN",424 "ks",425 "ks_IN",426 "ksb",427 "ksb_TZ",428 "ksf",429 "ksf_CM",430 "ksh",431 "ksh_DE",432 "kw",433 "kw_GB",434 "ky",435 "ky_KG",436 "lag",437 "lag_TZ",438 "lb",439 "lb_LU",440 "lg",441 "lg_UG",442 "lkt",443 "lkt_US",444 "ln",445 "ln_AO",446 "ln_CD",447 "ln_CF",448 "ln_CG",449 "lo",450 "lo_LA",451 "lrc",452 "lrc_IQ",453 "lrc_IR",454 "lt",455 "lt_LT",456 "lu",457 "lu_CD",458 "luo",459 "luo_KE",460 "luy",461 "luy_KE",462 "lv",463 "lv_LV",464 "mas",465 "mas_KE",466 "mas_TZ",467 "mer",468 "mer_KE",469 "mfe",470 "mfe_MU",471 "mg",472 "mg_MG",473 "mgh",474 "mgh_MZ",475 "mgo",476 "mgo_CM",477 "mk",478 "mk_MK",479 "ml",480 "ml_IN",481 "mn",482 "mn_MN",483 "mr",484 "mr_IN",485 "ms",486 "ms_BN",487 "ms_MY",488 "ms_SG",489 "mt",490 "mt_MT",491 "mua",492 "mua_CM",493 "my",494 "my_MM",495 "mzn",496 "mzn_IR",497 "naq",498 "naq_NA",499 "nb",500 "nb_NO",501 "nb_SJ",502 "nd",503 "nd_ZW",504 "nds",505 "nds_DE",506 "nds_NL",507 "ne",508 "ne_IN",509 "ne_NP",510 "nl",511 "nl_AW",512 "nl_BE",513 "nl_BQ",514 "nl_CW",515 "nl_NL",516 "nl_SR",517 "nl_SX",518 "nmg",519 "nmg_CM",520 "nn_NO",521 "nnh",522 "nnh_CM",523 "no",524 "no_NO",525 "no_NO_NY",526 "nus",527 "nus_SS",528 "nyn",529 "nyn_UG",530 "om",531 "om_ET",532 "om_KE",533 "or",534 "or_IN",535 "os",536 "os_GE",537 "os_RU",538 "pa",539 "pl",540 "pl_PL",541 "prg",542 "prg_001",543 "ps",544 "ps_AF",545 "pt",546 "pt_AO",547 "pt_BR",548 "pt_CH",549 "pt_CV",550 "pt_GQ",551 "pt_GW",552 "pt_LU",553 "pt_MO",554 "pt_MZ",555 "pt_PT",556 "pt_ST",557 "pt_TL",558 "qu",559 "qu_BO",560 "qu_EC",561 "qu_PE",562 "rm",563 "rm_CH",564 "rn",565 "rn_BI",566 "ro",567 "ro_MD",568 "ro_RO",569 "rof",570 "rof_TZ",571 "ru",572 "ru_BY",573 "ru_KG",574 "ru_KZ",575 "ru_MD",576 "ru_RU",577 "ru_UA",578 "rw",579 "rw_RW",580 "rwk",581 "rwk_TZ",582 "sah",583 "sah_RU",584 "saq",585 "saq_KE",586 "sbp",587 "sbp_TZ",588 "sd",589 "sd_PK",590 "se",591 "se_FI",592 "se_NO",593 "se_SE",594 "seh",595 "seh_MZ",596 "ses",597 "ses_ML",598 "sg",599 "sg_CF",600 "shi",601 "si",602 "si_LK",603 "sk",604 "sk_SK",605 "sl",606 "sl_SI",607 "smn",608 "smn_FI",609 "sn",610 "sn_ZW",611 "so",612 "so_DJ",613 "so_ET",614 "so_KE",615 "so_SO",616 "sq",617 "sq_AL",618 "sq_MK",619 "sq_XK",620 "sr",621 "sr_BA",622 "sr_CS",623 "sr_ME",624 "sr_RS",625 "sv",626 "sv_AX",627 "sv_FI",628 "sv_SE",629 "sw",630 "sw_CD",631 "sw_KE",632 "sw_TZ",633 "sw_UG",634 "ta",635 "ta_IN",636 "ta_LK",637 "ta_MY",638 "ta_SG",639 "te",640 "te_IN",641 "teo",642 "teo_KE",643 "teo_UG",644 "tg",645 "tg_TJ",646 "th",647 "th_TH",648 "ti",649 "ti_ER",650 "ti_ET",651 "tk",652 "tk_TM",653 "to",654 "to_TO",655 "tr",656 "tr_CY",657 "tr_TR",658 "tt",659 "tt_RU",660 "twq",661 "twq_NE",662 "tzm",663 "tzm_MA",664 "ug",665 "ug_CN",666 "uk",667 "uk_UA",668 "ur",669 "ur_IN",670 "ur_PK",671 "uz",672 "vai",673 "vi",674 "vi_VN",675 "vo",676 "vo_001",677 "vun",678 "vun_TZ",679 "wae",680 "wae_CH",681 "wo",682 "wo_SN",683 "xog",684 "xog_UG",685 "yav",686 "yav_CM",687 "yo",688 "yo_BJ",689 "yo_NG",690 "yue",691 "zgh",692 "zgh_MA",693 "zh",694 "zh_CN",695 "zh_HK",696 "zh_SG",697 "zh_TW",698 "zu",699 "zu_ZA",700)701/**702 * Returns an Arb that generates locales.703 *704 * Edgecases include a locale that only has a language (without country) and a locale705 * that has a variant.706 */707fun Arb.Companion.locale() = arbitrary(listOf("en", "ca_ES_VALENCIA")) { locales.random(it.random) }...

Full Screen

Full Screen

LocaleTest.kt

Source:LocaleTest.kt Github

copy

Full Screen

...3import io.kotest.matchers.collections.shouldContain4import io.kotest.matchers.string.shouldHaveMinLength5import io.kotest.property.Arb6import io.kotest.property.arbitrary.edgecases7import io.kotest.property.arbitrary.locale8import io.kotest.property.checkAll9class LocaleTest : FunSpec({10 test("locale happy path") {11 checkAll(Arb.locale()) { locale ->12 locale.shouldHaveMinLength(2)13 }14 }15 test("locales edgecases should contain a local without country") {16 Arb.locale().edgecases().shouldContain("en")17 }18 test("locales edgecases should contain a locale with a variant") {19 Arb.locale().edgecases().shouldContain("ca_ES_VALENCIA")20 }21})...

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1+import io.kotest.property.arbitrary.arbitrary2+import io.kotest.property.arbitrary.int3+import io.kotest.property.arbitrary.string4+import io.kotest.property.arbitrary.withEdgecases5+import io.kotest.property.arbitrary.withShrinker6+import io.kotest.property.arbitrary.withSource7+import io.kotest.property.arbitrary.withTransformer8+import io.kotest.property.arbitrary.withVersion9+import io.kotest.property.arbitrary.withWeight10+import io.kotest.property.arbitrary.withWeights11+import io.kotest.property.arbitrary.withoutEdgecases12+import io.kotest.property.arbitrary.withoutShrinker13+import io.kotest.property.arbitrary.withoutSource14+import io.kotest.property.arbitrary.withoutTransformer15+import io.kotest.property.arbitrary.withoutVersion16+import io.kotest.property.arbitrary.withoutWeight17+import io.kotest.property.arbitrary.withoutWeights18+import io.kotest.property.arbitrary.withoutVersion19+import io.kotest.property.shrinking.Shrinker20+import io.kotest.property.PropertyContext21+import io.kotest.property.PropertyTesting22+import io.kotest.property.arbitrary.Arb23+import io.kotest.property.arbitrary.bool24+import io.kotest.property.arbitrary.choice25+import io.kotest.property.arbitrary.constant26+import io.kotest.property.arbitrary.double27+import io.kotest.property.arbitrary.float28+import io.kotest.property.arbitrary.int29+import io.kotest.property.arbitrary.long30+import io.kotest.property.arbitrary.map31+import io.kotest.property.arbitrary.numericDoubles32+import io.kotest.property.arbitrary.numericFloats33+import io.kotest.property.arbitrary.numericLongs34+import io.kotest.property.arbitrary.string35+import io.kotest.property.arbitrary.withEdgecases36+import io.kotest.property.arbitrary.withShrinker37+import io.kotest.property.arbitrary.withSource38+import io.kotest.property.arbitrary.withTransformer39+import io.kotest.property.arbitrary.withVersion40+import io.k

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1 val locale = Locale.arbitrary().next()2 println(locale)3 val localDate = LocalDate.arbitrary().next()4 println(localDate)5 val localDateTime = LocalDateTime.arbitrary().next()6 println(localDateTime)7 val localTime = LocalTime.arbitrary().next()8 println(localTime)9 val month = Month.arbitrary().next()10 println(month)11 val monthDay = MonthDay.arbitrary().next()12 println(monthDay)13 val offsetDateTime = OffsetDateTime.arbitrary().next()14 println(offsetDateTime)15 val offsetTime = OffsetTime.arbitrary().next()16 println(offsetTime)17 val period = Period.arbitrary().next()18 println(period)19 val year = Year.arbitrary().next()20 println(year)21 val yearMonth = YearMonth.arbitrary().next()22 println(yearMonth)23 val zoneId = ZoneId.arbitrary().next()24 println(zoneId)25 val zoneOffset = ZoneOffset.arbitrary().next()26 println(zoneOffset)27 val zoneRegion = ZoneRegion.arbitrary().next()28 println(zoneRegion)29 val zonedDateTime = ZonedDateTime.arbitrary().next()30 println(zonedDateTime)

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1val locale = locale()2val localeArb = locale.arbitrary()3val enum = enum<MyEnum>()4val enumArb = enum.arbitrary()5val uuid = uuid()6val uuidArb = uuid.arbitrary()7val uuid = uuid()8val uuidArb = uuid.arbitrary()9val enum = enum<MyEnum>()10val enumArb = enum.arbitrary()11val uuid = uuid()12val uuidArb = uuid.arbitrary()13val uuid = uuid()14val uuidArb = uuid.arbitrary()15val enum = enum<MyEnum>()16val enumArb = enum.arbitrary()17val uuid = uuid()18val uuidArb = uuid.arbitrary()19val uuid = uuid()20val uuidArb = uuid.arbitrary()21val enum = enum<MyEnum>()22val enumArb = enum.arbitrary()23val uuid = uuid()24val uuidArb = uuid.arbitrary()25val uuid = uuid()26val uuidArb = uuid.arbitrary()27val enum = enum<MyEnum>()28val enumArb = enum.arbitrary()29val uuid = uuid()30val uuidArb = uuid.arbitrary()31val uuid = uuid()32val uuidArb = uuid.arbitrary()33val enum = enum<MyEnum>()

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1val arbLocale = Arb.locale()2val arbLocaleWithCountry = Arb.locale(allowedCountries = listOf(Locale.US, Locale.UK))3val arbLocaleWithLanguage = Arb.locale(allowedLanguages = listOf(Locale.US, Locale.UK))4val arbUuid = Arb.uuid()5val arbDuration = Arb.duration()6val arbDurationWithRange = Arb.duration(min = Duration.ofSeconds(1), max = Duration.ofSeconds(100))7val arbInstant = Arb.instant()8val arbInstantWithRange = Arb.instant(min = Instant.now(), max = Instant.now().plusSeconds(100))9val arbLocalDate = Arb.localDate()10val arbLocalDateWithRange = Arb.localDate(min = LocalDate.now(), max = LocalDate.now().plusDays(100))11val arbLocalDateTime = Arb.localDateTime()12val arbLocalDateTimeWithRange = Arb.localDateTime(min = LocalDateTime.now(), max = LocalDateTime.now().plusDays(100))13val arbLocalTime = Arb.localTime()14val arbLocalTimeWithRange = Arb.localTime(min = LocalTime.now(), max = LocalTime.now().plusHours(100))15val arbMonthDay = Arb.monthDay()16val arbMonthDayWithRange = Arb.monthDay(min = MonthDay.now(), max = MonthDay.now().plusDays(100))17val arbOffsetDateTime = Arb.offsetDateTime()18val arbOffsetDateTimeWithRange = Arb.offsetDateTime(min = OffsetDateTime.now(), max = OffsetDateTime.now().plusDays(100))19val arbOffsetTime = Arb.offsetTime()20val arbOffsetTimeWithRange = Arb.offsetTime(min = OffsetTime.now(), max = OffsetTime.now().plusHours(100))

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1data class Person(val name: String, val age: Int) {2 companion object {3 val arb: Arbitrary<Person> = arbitrary {4 Person(5 name = string().map { it.trim() }.filter { it.isNotBlank() }.next(),6 age = int(18..70).next()7 }8 }9}10data class Person(val name: String, val age: Int) {11 companion object {12 val arb: Arbitrary<Person> = arbitrary {13 Person(14 name = string().map { it.trim() }.filter { it.isNotBlank() }.next(),15 age = int(18..70).next()16 }17 }18}19data class Person(val name: String, val age: Int) {20 companion object {21 val arb: Arbitrary<Person> = arbitrary {22 Person(23 name = string().map { it.trim() }.filter { it.isNotBlank() }.next(),24 age = int(18..70).next()25 }26 }27}28data class Person(val name: String, val age: Int) {29 companion object {30 val arb: Arbitrary<Person> = arbitrary {31 Person(32 name = string().map { it.trim() }.filter { it.isNotBlank() }.next(),33 age = int(18..70).next()34 }35 }36}37data class Person(val name: String, val age: Int) {38 companion object {39 val arb: Arbitrary<Person> = arbitrary {40 Person(41 name = string().map { it.trim() }.filter { it.isNotBlank() }.next(),42 age = int(18..70).next()43 }44 }45}46data class Person(val name: String, val age: Int) {47 companion object {48 val arb: Arbitrary<Person> = arbitrary {49 Person(50 name = string().map { it.trim() }.filter { it.isNotBlank() }.next(),51 age = int(18..70).next()52 }53 }54}

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1 val locale = Locale("en", "US")2 val stringGen = Arb.string(1..10, locale)3 val string = stringGen.random()4 println(string)5 val locale = java.util.Locale("en", "US")6 val stringGen = Arb.string(1..10, locale)7 val string = stringGen.random()8 println(string)9}

Full Screen

Full Screen

locale

Using AI Code Generation

copy

Full Screen

1val arbLocale = Arb.locale()2val javaLocaleArb = Arb.javaLocale()3* `Arb.dateRange(min: Date, max: Date)`: Generates a random `Date` value between the specified4* `Arb.instantRange(min: Instant, max: Instant)`: Generates a random `Instant` value between the5* `Arb.jodaDateRange(min: DateMidnight, max: DateMidnight)`: Generates a random `DateMidnight` value6* `Arb.jodaDateTimeRange(min: DateTime, max: DateTime)`: Generates a random `DateTime` value between7* `Arb.jodaLocalDateRange(min: LocalDate, max: LocalDate)`: Generates a random `LocalDate` value8* `Arb.jodaLocalDateTimeRange(min: LocalDateTime, max: LocalDateTime)`: Generates a random

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.

Most used methods in locale

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful