diff --git a/.gitignore b/.gitignore
index 309db6a8..898c3b37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,7 +50,7 @@ captures/
!/.idea/runConfigurations/
!/.idea/inspectionProfiles/
!.idea/detekt.xml
-!.idea/ktlint.xml
+!.idea/ktlint-plugin.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
diff --git a/.idea/ktlint-plugin.xml b/.idea/ktlint-plugin.xml
new file mode 100644
index 00000000..bee5678e
--- /dev/null
+++ b/.idea/ktlint-plugin.xml
@@ -0,0 +1,6 @@
+
+
+
+ DISTRACT_FREE
+
+
\ No newline at end of file
diff --git a/.idea/ktlint.xml b/.idea/ktlint.xml
deleted file mode 100644
index 7efbd1de..00000000
--- a/.idea/ktlint.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- false
- true
-
-
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index c1e36464..fd4fe027 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 Rick Busarow
+ * Copyright (C) 2024 Rick Busarow
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -17,7 +17,6 @@ import builds.GROUP
import com.rickbusarow.doks.DoksTask
import com.rickbusarow.kgx.mustRunAfter
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import kotlin.text.Regex.Companion.escapeReplacement
buildscript {
@@ -37,7 +36,7 @@ doks {
rule("maven-with-version") {
regex = maven(GROUP)
- replacement = "$1:$2:${libs.versions.rickBusarow.kase.get() .escapeReplacement()}"
+ replacement = "$1:$2:${libs.versions.rickBusarow.kase.get().escapeReplacement()}"
}
rule("kgx-group") {
regex = "com\\.rickbusarow\\.kase"
diff --git a/detekt/detekt-config.yml b/detekt/detekt-config.yml
index 00cbc61b..dbc77d2c 100644
--- a/detekt/detekt-config.yml
+++ b/detekt/detekt-config.yml
@@ -594,6 +594,8 @@ potential-bugs:
- "kotlinx.coroutines.flow.*Flow"
- "java.util.stream.*Stream"
ignoreFunctionCall: []
+ excludes:
+ - "**/test/**"
ImplicitDefaultLocale:
active: true
ImplicitUnitReturnType:
diff --git a/kase-gradle/api/kase-gradle.api b/kase-gradle/api/kase-gradle.api
index dae05f14..28d6e2a2 100644
--- a/kase-gradle/api/kase-gradle.api
+++ b/kase-gradle/api/kase-gradle.api
@@ -440,6 +440,7 @@ public final class com/rickbusarow/kase/gradle/GradleTestEnvironmentFactory$Defa
public static fun getDslLanguage (Lcom/rickbusarow/kase/gradle/GradleTestEnvironmentFactory;)Lcom/rickbusarow/kase/gradle/DslLanguage;
public static fun getLocalM2Path (Lcom/rickbusarow/kase/gradle/GradleTestEnvironmentFactory;)Ljava/io/File;
public static fun newTestEnvironment (Lcom/rickbusarow/kase/gradle/GradleTestEnvironmentFactory;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/gradle/GradleTestEnvironment;
+ public static fun newTestEnvironment (Lcom/rickbusarow/kase/gradle/GradleTestEnvironmentFactory;Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/gradle/GradleTestEnvironment;
public static fun settingsFileDefault (Lcom/rickbusarow/kase/gradle/GradleTestEnvironmentFactory;Lcom/rickbusarow/kase/Kase;)Lcom/rickbusarow/kase/gradle/DslStringFactory;
}
@@ -599,6 +600,7 @@ public final class com/rickbusarow/kase/gradle/KaseGradleTest$DefaultImpls {
public static fun getLocalM2Path (Lcom/rickbusarow/kase/gradle/KaseGradleTest;)Ljava/io/File;
public static fun getVersionMatrix (Lcom/rickbusarow/kase/gradle/KaseGradleTest;)Lcom/rickbusarow/kase/KaseMatrix;
public static fun newTestEnvironment (Lcom/rickbusarow/kase/gradle/KaseGradleTest;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/gradle/GradleTestEnvironment;
+ public static fun newTestEnvironment (Lcom/rickbusarow/kase/gradle/KaseGradleTest;Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/gradle/GradleTestEnvironment;
public static fun settingsFileDefault (Lcom/rickbusarow/kase/gradle/KaseGradleTest;Lcom/rickbusarow/kase/Kase;)Lcom/rickbusarow/kase/gradle/DslStringFactory;
public static fun test (Lcom/rickbusarow/kase/gradle/KaseGradleTest;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;Lkotlin/jvm/functions/Function2;)V
public static fun testFactory (Lcom/rickbusarow/kase/gradle/KaseGradleTest;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
diff --git a/kase/api/kase.api b/kase/api/kase.api
index 1435bfe2..5d349bf0 100644
--- a/kase/api/kase.api
+++ b/kase/api/kase.api
@@ -2096,6 +2096,7 @@ public final class com/rickbusarow/kase/KaseTestFactory$DefaultImpls {
public static fun asTests (Lcom/rickbusarow/kase/KaseTestFactory;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
public static fun asTests (Lcom/rickbusarow/kase/KaseTestFactory;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
public static fun newTestEnvironment (Lcom/rickbusarow/kase/KaseTestFactory;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
+ public static fun newTestEnvironment (Lcom/rickbusarow/kase/KaseTestFactory;Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
public static fun test (Lcom/rickbusarow/kase/KaseTestFactory;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;Lkotlin/jvm/functions/Function2;)V
public static synthetic fun test$default (Lcom/rickbusarow/kase/KaseTestFactory;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
public static fun testFactory (Lcom/rickbusarow/kase/KaseTestFactory;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
@@ -2103,16 +2104,45 @@ public final class com/rickbusarow/kase/KaseTestFactory$DefaultImpls {
public static fun testFactory (Lcom/rickbusarow/kase/KaseTestFactory;[Lcom/rickbusarow/kase/Kase;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
}
+public final class com/rickbusarow/kase/KaseTestFactoryNodeBuilder : com/rickbusarow/kase/KaseTestFactory, com/rickbusarow/kase/TestNodeBuilder {
+ public fun (Lcom/rickbusarow/kase/KaseTestFactory;Lcom/rickbusarow/kase/TestNodeBuilder;)V
+ public fun asContainers (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun asContainers (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/util/stream/Stream;
+ public fun asContainers (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun asContainers (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/util/stream/Stream;
+ public fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public final fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
+ public fun asTests (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun asTests (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
+ public fun build ()Lorg/junit/jupiter/api/DynamicNode;
+ public fun container (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+ public fun getDisplayName ()Ljava/lang/String;
+ public fun getKases ()Ljava/util/List;
+ public fun getParent ()Lcom/rickbusarow/kase/TestNodeBuilder;
+ public fun getTestFunctionCoordinates ()Lcom/rickbusarow/kase/files/TestFunctionCoordinates;
+ public fun newTestEnvironment (Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
+ public fun newTestEnvironment (Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
+ public fun nodeSequence ()Lkotlin/sequences/Sequence;
+ public fun test (Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;Lkotlin/jvm/functions/Function2;)V
+ public fun test (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
+ public fun testFactory (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
+ public fun testFactory (Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
+ public fun testFactory ([Lcom/rickbusarow/kase/Kase;Lkotlin/jvm/functions/Function3;)Ljava/util/stream/Stream;
+}
+
public abstract interface class com/rickbusarow/kase/TestEnvironment : com/rickbusarow/kase/files/HasWorkingDir {
public static final field Companion Lcom/rickbusarow/kase/TestEnvironment$Companion;
public abstract fun tearDown ()V
}
public final class com/rickbusarow/kase/TestEnvironment$Companion {
+ public final fun invoke (Ljava/lang/String;[Ljava/lang/String;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
public final fun invoke (Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
- public final fun invoke ([Ljava/lang/String;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
+ public static synthetic fun invoke$default (Lcom/rickbusarow/kase/TestEnvironment$Companion;Ljava/lang/String;[Ljava/lang/String;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestEnvironment;
public static synthetic fun invoke$default (Lcom/rickbusarow/kase/TestEnvironment$Companion;Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestEnvironment;
- public static synthetic fun invoke$default (Lcom/rickbusarow/kase/TestEnvironment$Companion;[Ljava/lang/String;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestEnvironment;
}
public final class com/rickbusarow/kase/TestEnvironment$DefaultImpls {
@@ -2122,11 +2152,14 @@ public final class com/rickbusarow/kase/TestEnvironment$DefaultImpls {
public abstract interface class com/rickbusarow/kase/TestEnvironmentFactory {
public abstract fun newTestEnvironment (Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
+ public abstract fun newTestEnvironment (Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
}
public final class com/rickbusarow/kase/TestEnvironmentFactory$DefaultImpls {
public static fun newTestEnvironment (Lcom/rickbusarow/kase/TestEnvironmentFactory;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
+ public static fun newTestEnvironment (Lcom/rickbusarow/kase/TestEnvironmentFactory;Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;)Lcom/rickbusarow/kase/TestEnvironment;
public static synthetic fun newTestEnvironment$default (Lcom/rickbusarow/kase/TestEnvironmentFactory;Lcom/rickbusarow/kase/Kase;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestEnvironment;
+ public static synthetic fun newTestEnvironment$default (Lcom/rickbusarow/kase/TestEnvironmentFactory;Ljava/util/List;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestEnvironment;
}
public final class com/rickbusarow/kase/TestEnvironmentFactoryKt {
@@ -2134,28 +2167,26 @@ public final class com/rickbusarow/kase/TestEnvironmentFactoryKt {
public static synthetic fun test$default (Lcom/rickbusarow/kase/TestEnvironmentFactory;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
}
-public final class com/rickbusarow/kase/TestNodeBuilder {
- public fun (Ljava/lang/String;Lcom/rickbusarow/kase/files/TestFunctionCoordinates;Lcom/rickbusarow/kase/TestNodeBuilder;)V
- public final fun asContainers (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
- public final fun asContainers (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+public abstract interface class com/rickbusarow/kase/TestNodeBuilder : com/rickbusarow/kase/HasDisplayName {
+ public abstract fun asContainers (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun asContainers (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun asTests (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun build ()Lorg/junit/jupiter/api/DynamicNode;
+ public abstract fun container (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+ public abstract fun getParent ()Lcom/rickbusarow/kase/TestNodeBuilder;
+ public abstract fun getTestFunctionCoordinates ()Lcom/rickbusarow/kase/files/TestFunctionCoordinates;
+ public abstract fun nodeSequence ()Lkotlin/sequences/Sequence;
+ public abstract fun test (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
+}
+
+public final class com/rickbusarow/kase/TestNodeBuilder$DefaultImpls {
public static synthetic fun asContainers$default (Lcom/rickbusarow/kase/TestNodeBuilder;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestNodeBuilder;
public static synthetic fun asContainers$default (Lcom/rickbusarow/kase/TestNodeBuilder;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestNodeBuilder;
- public final fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/rickbusarow/kase/TestNodeBuilder;
- public final fun asTests (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/rickbusarow/kase/TestNodeBuilder;
- public final fun asTests (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/rickbusarow/kase/TestNodeBuilder;
public static synthetic fun asTests$default (Lcom/rickbusarow/kase/TestNodeBuilder;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestNodeBuilder;
- public static synthetic fun asTests$default (Lcom/rickbusarow/kase/TestNodeBuilder;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestNodeBuilder;
public static synthetic fun asTests$default (Lcom/rickbusarow/kase/TestNodeBuilder;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/rickbusarow/kase/TestNodeBuilder;
- public final fun container (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
- public fun equals (Ljava/lang/Object;)Z
- public final fun getName ()Ljava/lang/String;
- public final fun getNodes ()Ljava/util/List;
- public final fun getParent ()Lcom/rickbusarow/kase/TestNodeBuilder;
- public final fun getTestFunctionCoordinates ()Lcom/rickbusarow/kase/files/TestFunctionCoordinates;
- public fun hashCode ()I
- public final fun nodeSequence ()Lkotlin/sequences/Sequence;
- public final fun test (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
- public fun toString ()Ljava/lang/String;
}
public final class com/rickbusarow/kase/TestNodeBuilderKt {
diff --git a/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactory.kt b/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactory.kt
index e381c985..8e7f578e 100644
--- a/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactory.kt
+++ b/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactory.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 Rick Busarow
+ * Copyright (C) 2024 Rick Busarow
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -16,10 +16,12 @@
package com.rickbusarow.kase
import com.rickbusarow.kase.files.TestFunctionCoordinates
+import com.rickbusarow.kase.internal.DefaultTestNodeBuilder
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.DynamicTest
import java.util.stream.Stream
+import kotlin.streams.asStream
/**
* Common interface for creating dynamic tests with predefined
@@ -137,9 +139,9 @@ public interface KaseTestFactory :
* @return a stream of dynamic nodes representing the containers.
* @since 0.1.0
*/
- public fun Iterable.asContainers(
- testName: (K) -> String = { it.displayName },
- testAction: TestNodeBuilder.(K) -> Unit
+ public fun Iterable.asContainers(
+ testName: (K2) -> String = { it.displayName },
+ testAction: KaseTestFactoryNodeBuilder.(K2) -> Unit
): Stream = asSequence().asContainers(testName, testAction)
/**
@@ -152,10 +154,22 @@ public interface KaseTestFactory :
* @return a stream of dynamic nodes representing the containers.
* @since 0.1.0
*/
- public fun Sequence.asContainers(
- testName: (K) -> String = { it.displayName },
- testAction: TestNodeBuilder.(K) -> Unit
- ): Stream = com.rickbusarow.kase.testFactory {
- asContainers(testName, testAction)
- }
+ public fun Sequence.asContainers(
+ testName: (K2) -> String = { it.displayName },
+ testAction: KaseTestFactoryNodeBuilder.(K2) -> Unit
+ ): Stream = KaseTestFactoryNodeBuilder(
+ delegateFactory = this@KaseTestFactory,
+ delegateNodeBuilder = DefaultTestNodeBuilder(
+ displayName = "root",
+ testFunctionCoordinates = TestFunctionCoordinates.get(),
+ parent = null
+ )
+ )
+ .also {
+ for (k in this@asContainers) {
+ it.wrapContainer(testName(k)) { testAction(k) }
+ }
+ }
+ .nodeSequence()
+ .asStream()
}
diff --git a/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactoryNodeBuilder.kt b/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactoryNodeBuilder.kt
new file mode 100644
index 00000000..d869230c
--- /dev/null
+++ b/kase/src/main/kotlin/com/rickbusarow/kase/KaseTestFactoryNodeBuilder.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 Rick Busarow
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.rickbusarow.kase
+
+/**
+ * Enables the creation of multiple layers of nodes without
+ * losing the scope of the original TestEnvironment factory.
+ */
+public class KaseTestFactoryNodeBuilder(
+ delegateFactory: KaseTestFactory,
+ delegateNodeBuilder: TestNodeBuilder
+) : TestNodeBuilder by delegateNodeBuilder,
+ KaseTestFactory by delegateFactory {
+
+ /**
+ * Enables the creation of multiple layers of nodes without
+ * losing the scope of the original TestEnvironment factory.
+ */
+ public fun Iterable.asTests(testAction: T.(K) -> Unit): TestNodeBuilder {
+ return this@KaseTestFactoryNodeBuilder.also { builder ->
+ for (kase in this@asTests) {
+ test(kase.displayName) {
+ val parents = generateSequence(builder) { it.parent }
+ val names = parents.toList()
+ .dropLast(1)
+ .asReversed()
+ .map { it.displayName }
+ .plus(kase.displayName)
+ val environment = newTestEnvironment(names, testFunctionCoordinates)
+ environment.testAction(kase)
+ }
+ }
+ }
+ }
+
+ internal fun wrapContainer(
+ name: String,
+ init: KaseTestFactoryNodeBuilder.() -> Unit
+ ) {
+ container(name) del@{
+ val delegate: TestNodeBuilder = this@del
+
+ val child = KaseTestFactoryNodeBuilder(
+ delegateFactory = this@KaseTestFactoryNodeBuilder,
+ delegateNodeBuilder = delegate
+ )
+ child.init()
+ }
+ }
+}
diff --git a/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironment.kt b/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironment.kt
index 3277923b..d7af961f 100644
--- a/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironment.kt
+++ b/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironment.kt
@@ -56,7 +56,8 @@ public interface TestEnvironment : HasWorkingDir {
/**
* Creates a new [TestEnvironment] instance.
*
- * @param testParameterDisplayNames The display names of the test parameters, if any.
+ * @param testParameterDisplayName The display name of the first test parameter
+ * @param additionalNames optional additional names
* @param testFunctionCoordinates The [TestFunctionCoordinates]
* from which the test is being run.
* @return A new [TestEnvironment] instance.
@@ -65,10 +66,11 @@ public interface TestEnvironment : HasWorkingDir {
* @since 0.1.0
*/
public operator fun invoke(
- vararg testParameterDisplayNames: String,
+ testParameterDisplayName: String,
+ vararg additionalNames: String,
testFunctionCoordinates: TestFunctionCoordinates = TestFunctionCoordinates.get()
): TestEnvironment = DefaultTestEnvironment(
- testParameterDisplayNames = testParameterDisplayNames.toList(),
+ testParameterDisplayNames = listOf(testParameterDisplayName) + additionalNames,
testFunctionCoordinates = testFunctionCoordinates
)
}
diff --git a/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironmentFactory.kt b/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironmentFactory.kt
index b11e9339..04aaa8d5 100644
--- a/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironmentFactory.kt
+++ b/kase/src/main/kotlin/com/rickbusarow/kase/TestEnvironmentFactory.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 Rick Busarow
+ * Copyright (C) 2024 Rick Busarow
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -41,6 +41,23 @@ public interface TestEnvironmentFactory {
) as? T
?: error("Override `newTestEnvironment` in order to create this TestEnvironment type.")
}
+
+ /**
+ * Creates a new [TestEnvironment].
+ *
+ * @return A new [TestEnvironment] of type [T].
+ */
+ public fun newTestEnvironment(
+ testParameterDisplayNames: List,
+ testFunctionCoordinates: TestFunctionCoordinates = TestFunctionCoordinates.get()
+ ): T {
+ @Suppress("UNCHECKED_CAST")
+ return TestEnvironment(
+ testParameterDisplayNames,
+ testFunctionCoordinates = testFunctionCoordinates
+ ) as? T
+ ?: error("Override `newTestEnvironment` in order to create this TestEnvironment type.")
+ }
}
/**
diff --git a/kase/src/main/kotlin/com/rickbusarow/kase/TestNodeBuilder.kt b/kase/src/main/kotlin/com/rickbusarow/kase/TestNodeBuilder.kt
index 767d5f6c..6e748d0d 100644
--- a/kase/src/main/kotlin/com/rickbusarow/kase/TestNodeBuilder.kt
+++ b/kase/src/main/kotlin/com/rickbusarow/kase/TestNodeBuilder.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 Rick Busarow
+ * Copyright (C) 2024 Rick Busarow
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -16,10 +16,8 @@
package com.rickbusarow.kase
import com.rickbusarow.kase.files.TestFunctionCoordinates
-import dev.drewhamilton.poko.Poko
-import org.junit.jupiter.api.DynamicContainer
+import com.rickbusarow.kase.internal.DefaultTestNodeBuilder
import org.junit.jupiter.api.DynamicNode
-import org.junit.jupiter.api.DynamicTest
import java.util.stream.Stream
import kotlin.streams.asStream
@@ -41,8 +39,8 @@ import kotlin.streams.asStream
* @since 0.1.0
*/
public fun testFactory(init: TestNodeBuilder.() -> Unit): Stream {
- return TestNodeBuilder(
- name = "root",
+ return DefaultTestNodeBuilder(
+ displayName = "root",
testFunctionCoordinates = TestFunctionCoordinates.get(),
parent = null
)
@@ -67,28 +65,23 @@ public fun testFactory(init: TestNodeBuilder.() -> Unit): Stream DynamicNode> = mutableListOf()
+ /**
+ * Captured before executing any tests, meaning that it's the frame that called `asTests { ... }`
+ */
+ public val testFunctionCoordinates: TestFunctionCoordinates
+
+ /** the parent node, or `null` if this is the root container */
+ public val parent: TestNodeBuilder?
- @PublishedApi
- internal fun nodeSequence(): Sequence = nodes.asSequence().map { it() }
+ /** Converts this builder to a [DynamicNode] */
+ public fun build(): DynamicNode
- private fun build(): DynamicNode {
- return DynamicContainer.dynamicContainer(name, nodeSequence().asStream())
- }
+ /** */
+ public fun nodeSequence(): Sequence
/**
* Creates a dynamic test with the provided name and test logic, adds it to the list of nodes.
@@ -97,11 +90,7 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @param testAction a function containing the test logic.
* @since 0.1.0
*/
- public fun test(name: String, testAction: () -> Unit) {
- nodes.add {
- DynamicTest.dynamicTest(name, testFunctionCoordinates.testUriOrNull) { testAction() }
- }
- }
+ public fun test(name: String, testAction: () -> Unit)
/**
* Creates a dynamic container with the provided name
@@ -111,17 +100,7 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @param init a lambda with receiver that initializes the [TestNodeBuilder].
* @since 0.1.0
*/
- public fun container(name: String, init: TestNodeBuilder.() -> Unit) {
- nodes.add {
- TestNodeBuilder(
- name = name,
- testFunctionCoordinates = testFunctionCoordinates,
- parent = this
- )
- .apply(init)
- .build()
- }
- }
+ public fun container(name: String, init: TestNodeBuilder.() -> Unit)
/**
* Adds tests to the invoking [TestNodeBuilder] for each kaseParam of the
@@ -135,13 +114,9 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @since 0.1.0
*/
public fun Iterable.asTests(
- testName: (E) -> String = { (it as? HasDisplayName)?.displayName ?: it.toString() },
+ testName: (E) -> String = maybeDisplayNameOrToString(),
testAction: (E) -> Unit
- ): TestNodeBuilder = this@TestNodeBuilder.apply {
- for (element in this@asTests) {
- test(testName(element)) { testAction(element) }
- }
- }
+ ): TestNodeBuilder
/**
* Adds tests to the invoking [TestNodeBuilder] for each kaseParam of the
@@ -156,17 +131,25 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @since 0.1.0
*/
public fun Iterable.asTests(
- testName: (K) -> String = { (it as? HasDisplayName)?.displayName ?: it.toString() },
+ testName: (K) -> String,
testEnvironmentFactory: (kase: K) -> T,
testAction: T.(K) -> Unit
- ): TestNodeBuilder = this@TestNodeBuilder.apply {
- for (kase in this@asTests) {
- test(testName(kase)) {
- val environment = testEnvironmentFactory.invoke(kase)
- environment.testAction(kase)
- }
- }
- }
+ ): TestNodeBuilder
+
+ /**
+ * Adds tests to the invoking [TestNodeBuilder] for each kaseParam of the
+ * iterable. The tests themselves are defined by the [testAction] function.
+ *
+ * @param testEnvironmentFactory creates a new [TestEnvironment] for each test.
+ * @param testAction a function to define each test.
+ * @receiver the [TestNodeBuilder] to which tests will be added.
+ * @return the invoking [TestNodeBuilder], after adding the new tests.
+ * @since 0.1.0
+ */
+ public fun Iterable.asTests(
+ testEnvironmentFactory: (kase: K) -> T,
+ testAction: T.(K) -> Unit
+ ): TestNodeBuilder
/**
* Adds tests to the invoking [TestNodeBuilder] for each kaseParam of the
@@ -180,13 +163,9 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @since 0.1.0
*/
public fun Sequence.asTests(
- testName: (E) -> String = { (it as? HasDisplayName)?.displayName ?: it.toString() },
+ testName: (E) -> String = maybeDisplayNameOrToString(),
testAction: (E) -> Unit
- ): TestNodeBuilder = this@TestNodeBuilder.apply {
- for (element in this@asTests) {
- test(testName(element)) { testAction(element) }
- }
- }
+ ): TestNodeBuilder
/**
* Adds containers to the invoking [TestNodeBuilder] for each kaseParam of the
@@ -200,13 +179,9 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @since 0.1.0
*/
public fun Iterable.asContainers(
- testName: (E) -> String = { (it as? HasDisplayName)?.displayName ?: it.toString() },
+ testName: (E) -> String = maybeDisplayNameOrToString(),
testAction: TestNodeBuilder.(E) -> Unit
- ): TestNodeBuilder = this@TestNodeBuilder.apply {
- for (element in this@asContainers) {
- container(testName(element)) { testAction(element) }
- }
- }
+ ): TestNodeBuilder
/**
* Adds containers to the invoking [TestNodeBuilder] for each kaseParam of the
@@ -221,13 +196,9 @@ public class TestNodeBuilder @PublishedApi internal constructor(
* @since 0.1.0
*/
public fun Sequence.asContainers(
- testName: (E) -> String = { (it as? HasDisplayName)?.displayName ?: it.toString() },
+ testName: (E) -> String = maybeDisplayNameOrToString(),
testAction: TestNodeBuilder.(E) -> Unit
- ): TestNodeBuilder = this@TestNodeBuilder.apply {
- for (element in this@asContainers) {
- container(testName(element)) { testAction(element) }
- }
- }
+ ): TestNodeBuilder
}
/**
@@ -244,3 +215,6 @@ public fun Iterable.asContainers(
testName: (K) -> String = { it.displayName },
testAction: TestNodeBuilder.(K) -> Unit
): Stream = testFactory { asContainers(testName, testAction) }
+
+internal fun maybeDisplayNameOrToString(): (E) -> String =
+ { (it as? HasDisplayName)?.displayName ?: it.toString() }
diff --git a/kase/src/main/kotlin/com/rickbusarow/kase/internal/DefaultTestNodeBuilder.kt b/kase/src/main/kotlin/com/rickbusarow/kase/internal/DefaultTestNodeBuilder.kt
new file mode 100644
index 00000000..22daeefe
--- /dev/null
+++ b/kase/src/main/kotlin/com/rickbusarow/kase/internal/DefaultTestNodeBuilder.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2024 Rick Busarow
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.rickbusarow.kase.internal
+
+import com.rickbusarow.kase.Kase
+import com.rickbusarow.kase.TestEnvironment
+import com.rickbusarow.kase.TestNodeBuilder
+import com.rickbusarow.kase.files.TestFunctionCoordinates
+import dev.drewhamilton.poko.Poko
+import org.junit.jupiter.api.DynamicContainer
+import org.junit.jupiter.api.DynamicNode
+import org.junit.jupiter.api.DynamicTest
+import kotlin.streams.asStream
+
+@Poko
+internal class DefaultTestNodeBuilder @PublishedApi internal constructor(
+ override val displayName: String,
+ override val testFunctionCoordinates: TestFunctionCoordinates,
+ override val parent: TestNodeBuilder?
+) : TestNodeBuilder {
+
+ @PublishedApi
+ internal val nodes: MutableList<() -> DynamicNode> = mutableListOf()
+
+ override fun nodeSequence(): Sequence = nodes.asSequence().map { it() }
+
+ override fun build(): DynamicNode {
+ return DynamicContainer.dynamicContainer(displayName, nodeSequence().asStream())
+ }
+
+ override fun test(name: String, testAction: () -> Unit) {
+ nodes.add {
+ DynamicTest.dynamicTest(name, testFunctionCoordinates.testUriOrNull) { testAction() }
+ }
+ }
+
+ override fun container(name: String, init: TestNodeBuilder.() -> Unit) {
+ nodes.add {
+ DefaultTestNodeBuilder(
+ displayName = name,
+ testFunctionCoordinates = testFunctionCoordinates,
+ parent = this
+ )
+ .apply(init)
+ .build()
+ }
+ }
+
+ override fun Iterable.asTests(
+ testName: (E) -> String,
+ testAction: (E) -> Unit
+ ): TestNodeBuilder = this@DefaultTestNodeBuilder.apply {
+ for (element in this@asTests) {
+ test(testName(element)) { testAction(element) }
+ }
+ }
+
+ override fun Iterable.asTests(
+ testName: (K) -> String,
+ testEnvironmentFactory: (kase: K) -> T,
+ testAction: T.(K) -> Unit
+ ): TestNodeBuilder = this@DefaultTestNodeBuilder.apply {
+ for (kase in this@asTests) {
+ test(testName(kase)) {
+ val environment = testEnvironmentFactory.invoke(kase)
+ environment.testAction(kase)
+ }
+ }
+ }
+
+ override fun Iterable.asTests(
+ testEnvironmentFactory: (kase: K) -> T,
+ testAction: T.(K) -> Unit
+ ): TestNodeBuilder = this@DefaultTestNodeBuilder.apply {
+ for (kase in this@asTests) {
+ test(kase.displayName) {
+ val environment = testEnvironmentFactory.invoke(kase)
+ environment.testAction(kase)
+ }
+ }
+ }
+
+ override fun Sequence.asTests(
+ testName: (E) -> String,
+ testAction: (E) -> Unit
+ ): TestNodeBuilder = this@DefaultTestNodeBuilder.apply {
+ for (element in this@asTests) {
+ test(testName(element)) { testAction(element) }
+ }
+ }
+
+ override fun Iterable.asContainers(
+ testName: (E) -> String,
+ testAction: TestNodeBuilder.(E) -> Unit
+ ): TestNodeBuilder = this@DefaultTestNodeBuilder.apply {
+ for (element in this@asContainers) {
+ container(testName(element)) { testAction(element) }
+ }
+ }
+
+ override fun Sequence.asContainers(
+ testName: (E) -> String,
+ testAction: TestNodeBuilder.(E) -> Unit
+ ): TestNodeBuilder = this@DefaultTestNodeBuilder.apply {
+ for (element in this@asContainers) {
+ container(testName(element)) { testAction(element) }
+ }
+ }
+}
diff --git a/kase/src/test/kotlin/com/rickbusarow/kase/KaseTestFactoryTest.kt b/kase/src/test/kotlin/com/rickbusarow/kase/KaseTestFactoryTest.kt
index d1af3861..f7f9cebc 100644
--- a/kase/src/test/kotlin/com/rickbusarow/kase/KaseTestFactoryTest.kt
+++ b/kase/src/test/kotlin/com/rickbusarow/kase/KaseTestFactoryTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 Rick Busarow
+ * Copyright (C) 2024 Rick Busarow
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -20,8 +20,6 @@ import com.rickbusarow.kase.ParamTypes.B
import com.rickbusarow.kase.ParamTypes.C
import com.rickbusarow.kase.files.HasWorkingDir.Companion.baseWorkingDir
import com.rickbusarow.kase.files.HasWorkingDir.Companion.cleanStringForFileSystem
-import com.rickbusarow.kase.files.HasWorkingDir.Companion.div
-import com.rickbusarow.kase.stdlib.div
import io.kotest.matchers.shouldBe
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.TestFactory
@@ -68,6 +66,46 @@ class KaseTestFactoryTest : KaseTestFactory> {
}
}
}
+
+ @TestFactory
+ fun `scoping nested asTests`(): Stream {
+ val base = baseWorkingDir()
+
+ val functionDir = File("KaseTestFactoryTest")
+ .resolve(cleanStringForFileSystem("scoping nested asTests"))
+
+ return cs.asContainers { k1 ->
+
+ kases.asTests { k2 ->
+
+ val path = functionDir
+ .resolve(cleanStringForFileSystem(k1.displayName))
+ .resolve(cleanStringForFileSystem(k2.displayName))
+
+ workingDir.relativeTo(base) shouldBe path
+ }
+ }
+ }
+
+ @TestFactory
+ fun `scoping nested testFactory`(): Stream {
+ val base = baseWorkingDir()
+
+ val functionDir = File("KaseTestFactoryTest")
+ .resolve(cleanStringForFileSystem("scoping nested asTests"))
+
+ return cs.asContainers { k1 ->
+
+ testFactory { k2 ->
+
+ val path = functionDir
+ .resolve(cleanStringForFileSystem(k1.displayName))
+ .resolve(cleanStringForFileSystem(k2.displayName))
+
+ workingDir.relativeTo(base) shouldBe path
+ }
+ }
+ }
}
sealed class ParamTypes {