Best Kotest code snippet using io.kotest.engine.tags.tags.KClass.tags
TestEngineLauncher.kt
Source:TestEngineLauncher.kt
1@file:Suppress("unused", "MemberVisibilityCanBePrivate")2package io.kotest.engine3import io.kotest.common.runBlocking4import io.kotest.common.runPromise5import io.kotest.core.TagExpression6import io.kotest.core.config.AbstractProjectConfig7import io.kotest.core.config.ProjectConfiguration8import io.kotest.core.extensions.Extension9import io.kotest.core.project.TestSuite10import io.kotest.core.spec.Spec11import io.kotest.core.spec.SpecRef12import io.kotest.engine.config.ConfigManager13import io.kotest.engine.config.detectAbstractProjectConfigs14import io.kotest.engine.config.loadProjectConfigFromClassname15import io.kotest.engine.extensions.SpecifiedTagsTagExtension16import io.kotest.engine.listener.NoopTestEngineListener17import io.kotest.engine.listener.PinnedSpecTestEngineListener18import io.kotest.engine.listener.TeamCityTestEngineListener19import io.kotest.engine.listener.TestEngineListener20import io.kotest.engine.listener.ThreadSafeTestEngineListener21import io.kotest.mpp.log22import kotlin.reflect.KClass23/**24 * A builder class for creating and executing tests via the [TestEngine].25 *26 * Entry point for tests generated through the compiler plugins, and so the27 * public api cannot have breaking changes.28 */29class TestEngineLauncher(30 private val listener: TestEngineListener,31 private val projectConfiguration: ProjectConfiguration,32 private val configs: List<AbstractProjectConfig>,33 private val refs: List<SpecRef>,34 private val tagExpression: TagExpression?,35) {36 constructor() : this(37 NoopTestEngineListener,38 ProjectConfiguration(),39 emptyList(),40 emptyList(),41 null,42 )43 constructor(listener: TestEngineListener) : this(44 listener,45 ProjectConfiguration(),46 emptyList(),47 emptyList(),48 null,49 )50 /**51 * Convenience function to be called by the native code gen to set up the TeamCity listener.52 */53 fun withTeamCityListener(): TestEngineLauncher {54 return withListener(TeamCityTestEngineListener())55 }56 /**57 * Replace the listener with the given value.58 */59 fun withListener(listener: TestEngineListener): TestEngineLauncher {60 return TestEngineLauncher(61 listener = listener,62 projectConfiguration = projectConfiguration,63 configs = configs,64 refs = refs,65 tagExpression = tagExpression,66 )67 }68 fun withSpecs(vararg specs: Spec): TestEngineLauncher {69 return TestEngineLauncher(70 listener = listener,71 projectConfiguration = projectConfiguration,72 configs = configs,73 refs = specs.toList().map { SpecRef.Singleton(it) },74 tagExpression = tagExpression,75 )76 }77 fun withClasses(vararg specs: KClass<out Spec>): TestEngineLauncher = withClasses(specs.toList())78 fun withClasses(specs: List<KClass<out Spec>>): TestEngineLauncher {79 return TestEngineLauncher(80 listener = listener,81 projectConfiguration = projectConfiguration,82 configs = configs,83 refs = specs.toList().map { SpecRef.Reference(it) },84 tagExpression = tagExpression,85 )86 }87 /**88 * Adds a [AbstractProjectConfig] that was detected by the compiler plugin.89 */90 @Deprecated("Use withProjectConfig. Will be removed once compiler plugins are updated")91 fun withConfig(vararg projectConfig: AbstractProjectConfig): TestEngineLauncher {92 return withProjectConfig(*projectConfig)93 }94 /**95 * Adds a [AbstractProjectConfig] that was detected by the compiler plugin.96 */97 fun withProjectConfig(vararg projectConfig: AbstractProjectConfig): TestEngineLauncher {98 return TestEngineLauncher(99 listener = listener,100 projectConfiguration = projectConfiguration,101 configs = configs + projectConfig,102 refs = refs,103 tagExpression = tagExpression,104 )105 }106 fun withTagExpression(expression: TagExpression?): TestEngineLauncher {107 return TestEngineLauncher(108 listener = listener,109 projectConfiguration = projectConfiguration,110 configs = configs,111 refs = refs,112 tagExpression = expression,113 )114 }115 /**116 * Returns a copy of this launcher with the given [extensions] added to the configuration.117 *118 * Note: If after invoking this method, the [withConfiguration] is invoked, then any changes119 * here will be lost.120 */121 fun withExtensions(vararg extensions: Extension): TestEngineLauncher = withExtensions(extensions.toList())122 /**123 * Returns a copy of this launcher with the given [extensions] added to the configuration.124 *125 * Note: If after invoking this method, the [withConfiguration] is invoked, then any changes126 * here will be lost.127 */128 fun withExtensions(extensions: List<Extension>): TestEngineLauncher {129 extensions.forEach { projectConfiguration.registry.add(it) }130 return this131 }132 fun withConfiguration(configuration: ProjectConfiguration): TestEngineLauncher {133 return TestEngineLauncher(134 listener = listener,135 projectConfiguration = configuration,136 configs = configs,137 refs = refs,138 tagExpression = tagExpression,139 )140 }141 fun toConfig(): TestEngineConfig {142 // if the engine was configured with explicit tags, we register those via a tag extension143 tagExpression?.let { projectConfiguration.registry.add(SpecifiedTagsTagExtension(it)) }144 return TestEngineConfig(145 listener = ThreadSafeTestEngineListener(146 PinnedSpecTestEngineListener(147 listener148 )149 ),150 interceptors = testEngineInterceptors(),151 configuration = ConfigManager.initialize(152 projectConfiguration,153 configs + detectAbstractProjectConfigs() + listOfNotNull(loadProjectConfigFromClassname())154 ),155 tagExpression,156 )157 }158 fun testSuite(): TestSuite = TestSuite(refs)159 /**160 * Launch the [TestEngine] in an existing coroutine without blocking.161 */162 suspend fun async(): EngineResult {163 log { "TestEngineLauncher: Launching Test Engine" }164 val engine = TestEngine(toConfig())165 return engine.execute(testSuite())166 }167 /**168 * Launch the [TestEngine] created from this builder and block the thread until execution has completed.169 * This method will throw on JS.170 */171 fun launch(): EngineResult {172 log { "TestEngineLauncher: Launching Test Engine" }173 return runBlocking {174 val engine = TestEngine(toConfig())175 engine.execute(testSuite())176 }177 }178 /**179 * Launch the [TestEngine] created from this builder using a Javascript promise.180 * This method will throw on JVM or native.181 */182 fun promise() {183 log { "TestEngineLauncher: Launching Test Engine in Javascript promise" }184 runPromise {185 val engine = TestEngine(toConfig())186 engine.execute(testSuite())187 }188 }189}...
SpecExecutor.kt
Source:SpecExecutor.kt
1package io.kotest.engine.spec2import io.kotest.common.ExperimentalKotest3import io.kotest.common.Platform4import io.kotest.common.flatMap5import io.kotest.common.platform6import io.kotest.core.concurrency.CoroutineDispatcherFactory7import io.kotest.core.config.ProjectConfiguration8import io.kotest.core.spec.DslDrivenSpec9import io.kotest.core.spec.Spec10import io.kotest.core.spec.SpecRef11import io.kotest.core.test.TestCase12import io.kotest.core.test.TestResult13import io.kotest.engine.interceptors.EngineContext14import io.kotest.engine.interceptors.toProjectContext15import io.kotest.engine.listener.TestEngineListener16import io.kotest.engine.spec.interceptor.ApplyExtensionsInterceptor17import io.kotest.engine.spec.interceptor.ConfigurationInContextInterceptor18import io.kotest.engine.spec.interceptor.EnabledIfSpecInterceptor19import io.kotest.engine.spec.interceptor.FinalizeSpecInterceptor20import io.kotest.engine.spec.interceptor.IgnoreNestedSpecStylesInterceptor21import io.kotest.engine.spec.interceptor.IgnoredSpecInterceptor22import io.kotest.engine.spec.interceptor.PrepareSpecInterceptor23import io.kotest.engine.spec.interceptor.ProjectContextInterceptor24import io.kotest.engine.spec.interceptor.RequiresTagSpecInterceptor25import io.kotest.engine.spec.interceptor.SpecExtensionInterceptor26import io.kotest.engine.spec.interceptor.SpecFilterInterceptor27import io.kotest.engine.spec.interceptor.SpecFinishedInterceptor28import io.kotest.engine.spec.interceptor.SpecRefExtensionInterceptor29import io.kotest.engine.spec.interceptor.SpecRefInterceptor30import io.kotest.engine.spec.interceptor.SpecStartedInterceptor31import io.kotest.engine.spec.interceptor.SystemPropertySpecFilterInterceptor32import io.kotest.engine.spec.interceptor.TagsExcludedSpecInterceptor33import io.kotest.mpp.Logger34import io.kotest.mpp.bestName35import kotlin.reflect.KClass36/**37 * Executes a single [SpecRef].38 *39 * Uses a [TestEngineListener] to notify of events in the spec lifecycle.40 *41 * The spec executor has two levels of interceptors:42 * [io.kotest.engine.spec.interceptor.SpecRefInterceptor] are executed before the spec is created.43 * [io.kotest.engine.spec.interceptor.SpecInterceptor] are executed after the spec is created.44 *45 */46@ExperimentalKotest47class SpecExecutor(48 private val defaultCoroutineDispatcherFactory: CoroutineDispatcherFactory,49 private val context: EngineContext,50) {51 private val logger = Logger(SpecExecutorDelegate::class)52 private val extensions = SpecExtensions(context.configuration.registry)53 private val listener = context.listener54 suspend fun execute(ref: SpecRef) {55 logger.log { Pair(ref.kclass.bestName(), "Received $ref") }56 referenceInterceptors(ref)57 }58 suspend fun execute(kclass: KClass<out Spec>) {59 execute(SpecRef.Reference(kclass))60 }61 private suspend fun referenceInterceptors(ref: SpecRef) {62 val interceptors = listOfNotNull(63 if (platform == Platform.JVM) EnabledIfSpecInterceptor(listener, context.configuration.registry) else null,64 IgnoredSpecInterceptor(listener, context.configuration.registry),65 SpecFilterInterceptor(listener, context.configuration.registry),66 SystemPropertySpecFilterInterceptor(listener, context.configuration.registry),67 TagsExcludedSpecInterceptor(listener, context.configuration),68 if (platform == Platform.JVM) RequiresTagSpecInterceptor(listener, context.configuration, context.configuration.registry) else null,69 SpecRefExtensionInterceptor(context.configuration.registry),70 SpecStartedInterceptor(listener),71 SpecFinishedInterceptor(listener),72 if (platform == Platform.JVM) ApplyExtensionsInterceptor(context.configuration.registry) else null,73 PrepareSpecInterceptor(context.configuration.registry),74 FinalizeSpecInterceptor(context.configuration.registry),75 )76 val innerExecute: suspend (SpecRef) -> Result<Map<TestCase, TestResult>> = {77 createInstance(ref).flatMap { specInterceptors(it) }78 }79 logger.log { Pair(ref.kclass.bestName(), "Executing ${interceptors.size} reference interceptors") }80 interceptors.foldRight(innerExecute) { ext: SpecRefInterceptor, fn: suspend (SpecRef) -> Result<Map<TestCase, TestResult>> ->81 { ref -> ext.intercept(ref, fn) }82 }.invoke(ref)83 }84 private suspend fun specInterceptors(spec: Spec): Result<Map<TestCase, TestResult>> {85 val interceptors = listOfNotNull(86 if (platform == Platform.JS) IgnoreNestedSpecStylesInterceptor(listener, context.configuration.registry) else null,87 ProjectContextInterceptor(context.toProjectContext()),88 SpecExtensionInterceptor(context.configuration.registry),89 ConfigurationInContextInterceptor(context.configuration),90 )91 val initial: suspend (Spec) -> Result<Map<TestCase, TestResult>> = {92 try {93 val delegate = createSpecExecutorDelegate(listener, defaultCoroutineDispatcherFactory, context.configuration)94 logger.log { Pair(spec::class.bestName(), "delegate=$delegate") }95 Result.success(delegate.execute(spec))96 } catch (t: Throwable) {97 logger.log { Pair(spec::class.bestName(), "Error executing spec $t") }98 Result.failure(t)99 }100 }101 logger.log { Pair(spec::class.bestName(), "Executing ${interceptors.size} spec interceptors") }102 return interceptors.foldRight(initial) { ext, fn ->103 { spec -> ext.intercept(spec, fn) }104 }.invoke(spec)105 }106 /**107 * Creates an instance of the given [SpecRef], notifies users of the instantiation event108 * or instantiation failure, and returns a Result with the error or spec.109 *110 * After this method is called the spec is sealed.111 */112 private suspend fun createInstance(ref: SpecRef): Result<Spec> =113 ref.instance(context.configuration.registry)114 .onFailure { extensions.specInstantiationError(ref.kclass, it) }115 .flatMap { spec -> extensions.specInstantiated(spec).map { spec } }116 .onSuccess { if (it is DslDrivenSpec) it.seal() }117}118interface SpecExecutorDelegate {119 suspend fun execute(spec: Spec): Map<TestCase, TestResult>120}121@ExperimentalKotest122internal expect fun createSpecExecutorDelegate(123 listener: TestEngineListener,124 defaultCoroutineDispatcherFactory: CoroutineDispatcherFactory,125 configuration: ProjectConfiguration,126): SpecExecutorDelegate...
KotestEngineLauncher.kt
Source:KotestEngineLauncher.kt
1package io.kotest.engine2import io.kotest.common.KotestInternal3import io.kotest.core.TagExpression4import io.kotest.core.filter.SpecFilter5import io.kotest.core.filter.TestFilter6import io.kotest.core.spec.Spec7import io.kotest.engine.listener.CompositeTestEngineListener8import io.kotest.engine.listener.PinnedSpecTestEngineListener9import io.kotest.engine.listener.TestEngineListener10import io.kotest.engine.listener.ThreadSafeTestEngineListener11import kotlin.reflect.KClass12//import kotlin.script.templates.standard.ScriptTemplateWithArgs13/**14 * A builder class for creating and executing tests via the [TestEngine].15 */16@KotestInternal17@Suppress("DEPRECATION")18@Deprecated("Prefer TestEngineLauncher. Deprecated since 5.0")19class KotestEngineLauncher(20 private val listeners: List<TestEngineListener>,21 private val specs: List<KClass<out Spec>>,22 private val testFilters: List<TestFilter>,23 private val specFilters: List<SpecFilter>,24 private val tags: TagExpression?,25 private val scripts: List<KClass<*>>,26) {27 companion object {28 fun default(29 listeners: List<TestEngineListener>,30 specs: List<KClass<out Spec>>,31 tags: TagExpression?32 ): KotestEngineLauncher {33 return KotestEngineLauncher(34 listeners = listeners,35 specs = specs,36 scripts = emptyList(),37 testFilters = emptyList(),38 specFilters = emptyList(),39 tags = tags,40 )41 }42 }43 constructor() : this(emptyList(), emptyList(), emptyList(), emptyList(), null, emptyList())44 @Deprecated("This class is deprecated since 5.0")45 fun launch(): EngineResult {46 if (listeners.isEmpty())47 error("Cannot launch a KotestEngine without at least one TestEngineListener")48 val launcher = TestEngineLauncher(49 ThreadSafeTestEngineListener(50 PinnedSpecTestEngineListener(51 CompositeTestEngineListener(listeners)52 )53 )54 ).withExtensions(testFilters)55 .withExtensions(specFilters)56 .withTagExpression(tags)57 .withClasses(specs)58 return launcher.launch()59 }60 @Deprecated("This class is deprecated since 5.0")61 fun withFilter(filter: TestFilter) = withFilters(listOf(filter))62 @Deprecated("This class is deprecated since 5.0")63 fun withListener(listener: TestEngineListener) = KotestEngineLauncher(64 listeners = this.listeners + listener,65 specs = specs,66 testFilters = testFilters,67 specFilters = specFilters,68 tags = tags,69 scripts = scripts,70 )71 @Deprecated("This class is deprecated since 5.0")72 fun withDumpConfig(dump: Boolean) = KotestEngineLauncher(73 listeners = listeners,74 specs = specs,75 testFilters = testFilters,76 specFilters = specFilters,77 tags = tags,78 scripts = scripts,79 )80 @Deprecated("This class is deprecated since 5.0")81 fun withSpecFilters(filters: List<SpecFilter>): KotestEngineLauncher {82 return KotestEngineLauncher(83 listeners = listeners,84 specs = specs,85 testFilters = testFilters,86 specFilters = specFilters + filters,87 tags = tags,88 scripts = scripts,89 )90 }91 @Deprecated("This class is deprecated since 5.0")92 fun withTestFilters(filters: List<TestFilter>): KotestEngineLauncher {93 return KotestEngineLauncher(94 listeners = listeners,95 specs = specs,96 testFilters = testFilters + filters,97 specFilters = specFilters,98 tags = tags,99 scripts = scripts,100 )101 }102 @Deprecated("This class is deprecated since 5.0")103 fun withFilters(filters: List<TestFilter>): KotestEngineLauncher = withTestFilters(filters)104 @Deprecated("This class is deprecated since 5.0")105 fun withScripts(scripts: List<KClass<*>>): KotestEngineLauncher {106 return KotestEngineLauncher(107 listeners = listeners,108 specs = specs,109 testFilters = testFilters,110 specFilters = specFilters,111 tags = tags,112 scripts = scripts,113 )114 }115 @Deprecated("This class is deprecated since 5.0")116 fun withSpec(klass: KClass<out Spec>) = withSpecs(listOf(klass))117 @Deprecated("This class is deprecated since 5.0")118 fun withSpecs(vararg specs: KClass<out Spec>) = withSpecs(specs.toList())119 @Deprecated("This class is deprecated since 5.0")120 fun withSpecs(specs: List<KClass<out Spec>>): KotestEngineLauncher {121 return KotestEngineLauncher(122 listeners = listeners,123 specs = specs,124 testFilters = testFilters,125 specFilters = specFilters,126 tags = tags,127 scripts = scripts,128 )129 }130 @Deprecated("This class is deprecated since 5.0")131 fun withTags(tags: TagExpression?): KotestEngineLauncher {132 return KotestEngineLauncher(133 listeners = listeners,134 specs = specs,135 testFilters = testFilters,136 specFilters = specFilters,137 tags = tags,138 scripts = scripts,139 )140 }141}...
DefaultDisplayNameFormatter.kt
Source:DefaultDisplayNameFormatter.kt
1package io.kotest.engine.test.names2import io.kotest.common.Platform3import io.kotest.common.platform4import io.kotest.core.annotation.displayname.wrapper5import io.kotest.core.config.ExtensionRegistry6import io.kotest.core.config.ProjectConfiguration7import io.kotest.core.extensions.DisplayNameFormatterExtension8import io.kotest.core.names.DisplayNameFormatter9import io.kotest.core.names.TestNameCase10import io.kotest.core.spec.DisplayName11import io.kotest.core.test.TestCase12import io.kotest.mpp.annotation13import io.kotest.mpp.bestName14import kotlin.reflect.KClass15fun getDisplayNameFormatter(registry: ExtensionRegistry, configuration: ProjectConfiguration): DisplayNameFormatter {16 return registry.all()17 .filterIsInstance<DisplayNameFormatterExtension>()18 .firstOrNull()19 ?.formatter() ?: DefaultDisplayNameFormatter(configuration)20}21/**22 * A default implementation of [DisplayNameFormatter].23 * Used when there are no registered [io.kotest.core.extensions.DisplayNameFormatterExtension]s.24 */25class DefaultDisplayNameFormatter(26 private val configuration: ProjectConfiguration,27) : DisplayNameFormatter {28 constructor() : this(ProjectConfiguration())29 override fun format(testCase: TestCase): String {30 val prefix = when (configuration.includeTestScopeAffixes ?: testCase.name.defaultAffixes) {31 true -> testCase.name.prefix ?: ""32 false -> ""33 }34 val suffix = when (configuration.includeTestScopeAffixes ?: testCase.name.defaultAffixes) {35 true -> testCase.name.suffix ?: ""36 false -> ""37 }38 val displayName = if (prefix.isBlank()) {39 when (configuration.testNameCase) {40 TestNameCase.Sentence -> testCase.name.testName.capital() + suffix41 TestNameCase.InitialLowercase -> testCase.name.testName.uncapitalize() + suffix42 TestNameCase.Lowercase -> testCase.name.testName.lowercase() + suffix43 else -> testCase.name.testName + suffix44 }45 } else {46 when (configuration.testNameCase) {47 TestNameCase.Sentence -> "${prefix.capital()}${testCase.name.testName.uncapitalize()}$suffix"48 TestNameCase.InitialLowercase -> "${prefix.uncapitalize()}${testCase.name.testName.uncapitalize()}$suffix"49 TestNameCase.Lowercase -> "${prefix.lowercase()}${testCase.name.testName.lowercase()}$suffix"50 else -> "$prefix${testCase.name.testName}$suffix"51 }52 }53 val name = if (configuration.testNameAppendTags) {54 return appendTagsInDisplayName(testCase, displayName)55 } else {56 displayName57 }58 return when (val parent = testCase.parent) {59 null -> name60 else -> if (configuration.displayFullTestPath) format(parent) + " " + name else name61 }62 }63 /**64 * Returns a formatted display name for this spec class.65 *66 * If the spec has been annotated with [DisplayName] (on supported platforms), then that will be used,67 * otherwise the default is to use the fully qualified class name.68 *69 * Note: This name must be globally unique. Two specs, even in different packages,70 * cannot share the same names, so if [DisplayName] is used, developers must ensure it does not71 * clash with another spec.72 */73 override fun format(kclass: KClass<*>): String {74 return when (platform) {75 Platform.JVM -> kclass.annotation<DisplayName>()?.wrapper ?: kclass.bestName()76 Platform.JS -> kclass.bestName()77 Platform.Native -> kclass.bestName()78 }79 }80}81fun appendTagsInDisplayName(testCase: TestCase, displayName: String): String {82 val tagNames = testCase.config.tags.joinToString(", ")83 return if (tagNames.isBlank()) {84 displayName85 } else {86 "${displayName}[tags = $tagNames]"87 }88}89private fun String.capital() = this.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }90private fun String.uncapitalize() =91 this[0].lowercaseChar() + substring(1 until this.length)...
active.kt
Source:active.kt
1package io.kotest.engine.tags2import io.kotest.core.Tag3import io.kotest.core.spec.Spec4import kotlin.reflect.KClass5/**6 * Returns true if the given [Spec] class could contain an active test based on further tags.7 * Returns false if the spec has been explicitly excluded and should not be instantiated.8 */9fun Expression?.isPotentiallyActive(kclass: KClass<out Spec>): Boolean {10 // nothing is excluded if the expression is null11 if (this == null) return true12 // if the class is not tagged then it is not excluded13 val tags = kclass.tags()14 if (tags.isEmpty()) return true15 return isPotentiallyActive(tags.toSet()) ?: true16}17internal fun Expression.isPotentiallyActive(tags: Set<Tag>): Boolean? {18 return when (this) {19 is Expression.Or -> left.isPotentiallyActive(tags) ?: true || right.isPotentiallyActive(tags) ?: true20 is Expression.And -> left.isPotentiallyActive(tags) ?: true && right.isPotentiallyActive(tags) ?: true21 is Expression.Not -> expr.isPotentiallyActive(tags)?.not()22 is Expression.Identifier -> if (tags.map { it.name }.contains(ident)) true else null23 }24}25/**26 * Returns true if the the given tag should be considered active based27 * on the current tag expression.28 */29fun Expression?.isActive(tag: Tag): Boolean = isActive(setOf(tag))30/**31 * Returns true if the the given set of tags should be considered active based32 * on the current tag expression.33 */34fun Expression?.isActive(tags: Set<Tag>): Boolean {35 // everything is always active when no tag expression is provided36 if (this == null) return true37 return evaluate(tags, this)38}39private fun evaluate(tags: Set<Tag>, expression: Expression): Boolean {40 return when (expression) {41 is Expression.Or -> evaluate(tags, expression.left) || evaluate(tags, expression.right)42 is Expression.And -> evaluate(tags, expression.left) && evaluate(tags, expression.right)43 is Expression.Not -> !evaluate(tags, expression.expr)44 is Expression.Identifier -> tags.map { it.name }.contains(expression.ident)45 }46}...
RequiresTagSpecInterceptor.kt
Source:RequiresTagSpecInterceptor.kt
1package io.kotest.engine.spec.interceptor2import io.kotest.common.flatMap3import io.kotest.core.NamedTag4import io.kotest.core.annotation.RequiresTag5import io.kotest.core.annotation.requirestag.wrapper6import io.kotest.core.config.ProjectConfiguration7import io.kotest.core.config.ExtensionRegistry8import io.kotest.core.filter.SpecFilter9import io.kotest.core.spec.SpecRef10import io.kotest.core.test.TestCase11import io.kotest.core.test.TestResult12import io.kotest.engine.listener.TestEngineListener13import io.kotest.engine.spec.SpecExtensions14import io.kotest.engine.tags.isActive15import io.kotest.engine.tags.parse16import io.kotest.engine.tags.runtimeTags17import io.kotest.mpp.annotation18/**19 * A [SpecFilter] which will ignore specs if they are annotated with @[RequiresTag]20 * and those tags are not present in the runtime tags.21 */22internal class RequiresTagSpecInterceptor(23 private val listener: TestEngineListener,24 private val configuration: ProjectConfiguration,25 private val registry: ExtensionRegistry,26) : SpecRefInterceptor {27 override suspend fun intercept(28 ref: SpecRef,29 fn: suspend (SpecRef) -> Result<Map<TestCase, TestResult>>30 ): Result<Map<TestCase, TestResult>> {31 return when (val annotation = ref.kclass.annotation<RequiresTag>()) {32 null -> fn(ref)33 else -> {34 val requiredTags = annotation.wrapper.map { NamedTag(it) }.toSet()35 val expr = configuration.runtimeTags().parse()36 if (requiredTags.isEmpty() || expr.isActive(requiredTags)) {37 fn(ref)38 } else {39 runCatching { listener.specIgnored(ref.kclass, "Disabled by @RequiresTag") }40 .flatMap { SpecExtensions(registry).ignored(ref.kclass, "Disabled by @RequiresTag") }41 .map { emptyMap() }42 }43 }44 }45 }46}...
TagsExcludedDiscoveryExtension.kt
Source:TagsExcludedDiscoveryExtension.kt
1package io.kotest.engine.spec.interceptor2import io.kotest.common.flatMap3import io.kotest.core.TagExpression4import io.kotest.core.config.ProjectConfiguration5import io.kotest.core.spec.Spec6import io.kotest.core.spec.SpecRef7import io.kotest.core.test.TestCase8import io.kotest.core.test.TestResult9import io.kotest.engine.listener.TestEngineListener10import io.kotest.engine.spec.SpecExtensions11import io.kotest.engine.tags.isPotentiallyActive12import io.kotest.engine.tags.parse13import io.kotest.engine.tags.runtimeTags14/**15 * Filters any [Spec] that can be eagerly excluded based on the @[TagExpression] annotation at the class level.16 */17class TagsExcludedSpecInterceptor(18 private val listener: TestEngineListener,19 private val conf: ProjectConfiguration,20) : SpecRefInterceptor {21 private val extensions = SpecExtensions(conf.registry)22 override suspend fun intercept(23 ref: SpecRef,24 fn: suspend (SpecRef) -> Result<Map<TestCase, TestResult>>25 ): Result<Map<TestCase, TestResult>> {26 val potentiallyActive = conf.runtimeTags().parse().isPotentiallyActive(ref.kclass)27 return if (potentiallyActive) {28 fn(ref)29 } else {30 runCatching { listener.specIgnored(ref.kclass, null) }31 .flatMap { extensions.ignored(ref.kclass, "Skipped by tags") }32 .map { emptyMap() }33 }34 }35}...
tags.kt
Source:tags.kt
1package io.kotest.engine.tags2import io.kotest.core.NamedTag3import io.kotest.core.Tag4import io.kotest.mpp.annotation5import kotlin.reflect.KClass6/**7 * Returns the tags specified on the given class from the @Tags annotation if present.8 */9actual fun KClass<*>.tags(): Set<Tag> {10 val annotation = annotation<io.kotest.core.annotation.Tags>() ?: return emptySet()11 return annotation.values.map { NamedTag(it) }.toSet()12}...
KClass.tags
Using AI Code Generation
1@Tag("tag1")2@Tag("tag2")3class TaggedTest2 : FunSpec({4 test("test") {5 }6})
KClass.tags
Using AI Code Generation
1+class ClassTagsTest : FunSpec({2+ test("test1") {3+ val tags = ClassTagsTest::class.tags()4+ tags.shouldContain("ClassTag1")5+ tags.shouldContain("ClassTag2")6+ }7+})8+class TestCaseTagsTest : FunSpec({9+ test("test1").config(tags = setOf("TestCaseTag1")) {10+ }11+ test("test2").config(tags = setOf("TestCaseTag2")) {12+ }13+})14+@Tag("ContainerTag1")15+class ContainerTagsTest : FunSpec({16+ test("test1") {17+ }18+ test("test2") {19+ }20+})
KClass.tags
Using AI Code Generation
1tags = tags() + this::class.tags()2test("test 1").config(tags = setOf(MyTag)) {3}4test("test 1").config(tags = setOf(MyTag, MyOtherTag)) {5}6test("test 1").config(excludeTags = setOf(MyTag)) {7}8test("test 1").config(excludeTags = setOf(MyTag, MyOtherTag)) {9}
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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!