Skip to content

Commit

Permalink
fix(RequiresTagInterceptor): Add fix to handle scenario where no tags…
Browse files Browse the repository at this point in the history
… are present in the runtime tags, but some specs are annotated with @RequiresTag() (#3532)

* test(RequiresTagInterceptor): Add tests for interceptor, with failing test for !3531

* fix(RequiresTagInterceptor): Add fix to handle scenario where no tags are present in the runtime tags, but some specs are annotated with @RequiresTag()

Ref #3531

* fixup! test(RequiresTagInterceptor): Add tests for interceptor, with failing test for !3531

---------

Co-authored-by: Emil Kantis <emil.kantis@protonmail.com>
  • Loading branch information
zakhenry and Kantis committed Jul 26, 2023
1 parent 7727acf commit 2d59bf4
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ public final class io/kotest/engine/listener/CollectingTestEngineListener : io/k
public final fun result (Ljava/lang/String;)Lio/kotest/core/test/TestResult;
public final fun setErrors (Z)V
public fun specFinished (Lkotlin/reflect/KClass;Lio/kotest/core/test/TestResult;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun specIgnored (Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun testFinished (Lio/kotest/core/test/TestCase;Lio/kotest/core/test/TestResult;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun testIgnored (Lio/kotest/core/test/TestCase;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun toKey (Lio/kotest/core/test/TestCase;)Lio/kotest/engine/listener/CollectingTestEngineListener$TestCaseKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class CollectingTestEngineListener : AbstractTestEngineListener() {
if (result.isErrorOrFailure) errors = true
}

override suspend fun specIgnored(kclass: KClass<*>, reason: String?) {
specs[kclass] = TestResult.Ignored(reason)
}

override suspend fun testIgnored(testCase: TestCase, reason: String?) {
tests[testCase.toKey()] = TestResult.Ignored(reason)
names.add(testCase.name.testName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,7 @@ class PinnedSpecTestEngineListener(val listener: TestEngineListener) : TestEngin
}

override suspend fun specIgnored(kclass: KClass<*>, reason: String?) {
if (runningSpec == kclass.toDescriptor().path().value) {
listener.specIgnored(kclass, reason)
} else {
queue {
specIgnored(kclass, reason)
}
}
listener.specIgnored(kclass, reason)
}

override suspend fun testStarted(testCase: TestCase) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal class RequiresTagInterceptor(
else -> {
val requiredTags = annotation.wrapper.map { NamedTag(it) }.toSet()
val expr = configuration.runtimeTagExpression().parse()
if (requiredTags.isEmpty() || expr.isActive(requiredTags)) {
if (requiredTags.isEmpty() || (expr != null && expr.isActive(requiredTags))) {
fn(ref)
} else {
runCatching { listener.specIgnored(ref.kclass, "Disabled by @RequiresTag") }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.sksamuel.kotest.engine.tags

import io.kotest.assertions.assertSoftly
import io.kotest.core.TagExpression
import io.kotest.core.annotation.RequiresTag
import io.kotest.core.spec.style.ExpectSpec
import io.kotest.core.spec.style.FunSpec
import io.kotest.engine.TestEngineLauncher
import io.kotest.engine.listener.CollectingTestEngineListener
import io.kotest.matchers.booleans.shouldBeFalse
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.shouldBe


class RequiresTagTest : FunSpec({
test("RequiresTagInterceptor should include spec if the tag expression contains the required tag") {
val collector = CollectingTestEngineListener()

TestEngineLauncher(collector)
.withTagExpression(TagExpression("Foo"))
.withClasses(TaggedSpec::class)
.launch()

collector
.specs[TaggedSpec::class].shouldNotBeNull()
.isIgnored.shouldBeFalse()
}

test("RequiresTagInterceptor should exclude spec if the tag expression does not contain the required tag") {
val collector = CollectingTestEngineListener()

TestEngineLauncher(collector)
.withClasses(TaggedSpec::class)
.withTagExpression(TagExpression("UnrelatedTag"))
.launch()

assertSoftly(collector.specs[TaggedSpec::class]) {
shouldNotBeNull()
isIgnored.shouldBeTrue()
reasonOrNull shouldBe "Disabled by @RequiresTag"
}
}

test("RequiresTagInterceptor should exclude spec if the tag expression is blank") {
val collector = CollectingTestEngineListener()

TestEngineLauncher(collector)
.withClasses(TaggedSpec::class)
.withTagExpression(TagExpression.Empty)
.launch()

collector
.specs[TaggedSpec::class].shouldNotBeNull()
.isIgnored.shouldBeTrue()
}
})

@RequiresTag("Foo")
private class TaggedSpec : ExpectSpec()

0 comments on commit 2d59bf4

Please sign in to comment.