@@ -5,30 +5,38 @@ import io.kotest.core.spec.Spec
5
5
import io.kotest.engine.TestEngineLauncher
6
6
import io.kotest.engine.cli.parseArgs
7
7
import io.kotest.engine.extensions.ProvidedDescriptorFilter
8
- import io.kotest.engine.launcher.LauncherArgs.CANDIDATES
8
+ import io.kotest.engine.launcher.LauncherArgs.ARG_CANDIDATES
9
+ import io.kotest.engine.launcher.LauncherArgs.ARG_LISTENER
10
+ import io.kotest.engine.launcher.LauncherArgs.ARG_TERMCOLOR
9
11
import io.kotest.engine.launcher.LauncherArgs.DESCRIPTOR
10
- import io.kotest.engine.launcher.LauncherArgs.LISTENER
11
12
import io.kotest.engine.launcher.LauncherArgs.REPORTER
12
13
import io.kotest.engine.launcher.LauncherArgs.SPEC
13
- import io.kotest.engine.launcher.LauncherArgs.TERMCOLORS
14
14
import io.kotest.engine.launcher.LauncherArgs.TESTPATH
15
15
import io.kotest.engine.launcher.LauncherArgs.WRITER
16
16
import io.kotest.engine.listener.CollectingTestEngineListener
17
17
import io.kotest.engine.listener.CompositeTestEngineListener
18
18
import io.kotest.engine.listener.LoggingTestEngineListener
19
19
import io.kotest.engine.listener.PinnedSpecTestEngineListener
20
+ import io.kotest.engine.listener.TestEngineListener
20
21
import io.kotest.engine.listener.ThreadSafeTestEngineListener
21
22
import io.kotest.engine.runBlocking
22
23
import kotlin.reflect.KClass
23
24
import kotlin.system.exitProcess
24
25
25
26
object LauncherArgs {
26
27
27
- const val CANDIDATES = " candidates"
28
+ // required to pass the candidates to the engine
29
+ const val ARG_CANDIDATES = " candidates"
28
30
29
31
// these are optional
30
- const val LISTENER = " listener"
31
- const val TERMCOLORS = " termcolors"
32
+
33
+ // used to specify if we want team city or console output
34
+ const val ARG_LISTENER = " --listener"
35
+
36
+ // used to specify the color of the output
37
+ const val ARG_TERMCOLOR = " --termcolor"
38
+
39
+ // used to filter to a single spec or test within a spec
32
40
const val DESCRIPTOR = " descriptor"
33
41
34
42
// these are deprecated kotest 5 flags kept for backwards compatibility
@@ -41,11 +49,12 @@ object LauncherArgs {
41
49
/* *
42
50
* The entry point for the launcher.
43
51
*
44
- * Parses the cli args, creates the listeners and creates a test launcher using a [TestEngineLauncherBuilder].
52
+ * Parses the cli args, creates [io.kotest.engine.listener.TestEngineListener]s and invokes
53
+ * the test engine using a [TestEngineLauncher].
45
54
*
46
55
* --- IMPORTANT NOTE ---
47
56
* This is used by the Gradle and Intellij plugins (and other third party clients).
48
- * Therefore, the package name and contract for this main method *MUST* remain backwards compatible.
57
+ * Therefore, the package name and contract for this main method ** MUST* * remain backwards compatible.
49
58
*/
50
59
fun main (args : Array <String >) {
51
60
@@ -54,37 +63,28 @@ fun main(args: Array<String>) {
54
63
val launcherArgs = parseArgs(args.toList())
55
64
// println("Parsed args: $launcherArgs")
56
65
57
- // The launcher *must* be told what classes are available on the classpath, the engine will not perform scanning.
66
+ // The enigne *must* be given the classes to execute - in Kotest 6 the engine does not perform scanning
58
67
// It is the responsibility of the caller to pass this information.
59
- // In Kotest 5 the argument was called --spec but was changed to --candidates in Kotest 6,
68
+ // In Kotest 5 a similar argument was called --spec to specify a single class but kotest 6 uses --candidates
60
69
// we must support both for backwards compatibility
61
- val candidatesArg = launcherArgs[CANDIDATES ]
70
+ // todo do we need to do this? if people are upgrading to kotest 6 they can update the plugin too?
71
+ val candidatesArg = launcherArgs[ARG_CANDIDATES ]
62
72
? : launcherArgs[SPEC ]
63
- ? : error(" The $CANDIDATES arg must be provided" )
73
+ ? : error(" The $ARG_CANDIDATES arg must be provided" )
64
74
65
75
@Suppress(" UNCHECKED_CAST" )
66
76
val classes = candidatesArg.split(' ;' ).map { Class .forName(it).kotlin as KClass <out Spec > }
67
77
68
78
// we support --descriptor to support an exact descriptor path as a way to run a single test
69
- val descriptorFilter = launcherArgs[DESCRIPTOR ]?.let { descriptor ->
70
- // println("Making a filter from input $descriptor")
71
- ProvidedDescriptorFilter (DescriptorPaths .parse(descriptor))
72
- }
79
+ val descriptorFilter = buildDescriptorFilter(launcherArgs)
73
80
74
81
// Kotest 5 supported --testpath and didn't support the a descriptor selector, only the test name
75
82
// but we can combine that with the --spec arg which we know must be present in kotest 5 if testpath is
76
- val descriptorFilterKotest5 = launcherArgs[TESTPATH ]?.let { test ->
77
- launcherArgs[SPEC ]?.let { spec ->
78
- ProvidedDescriptorFilter (DescriptorPaths .parse(" $spec /$test " ))
79
- }
80
- }
83
+ // this exists so people can upgrade to kotest 6 but keep the old plugin
84
+ // todo do we need to do this? if people are upgrading to kotest 6 they can update the plugin too?
85
+ val descriptorFilterKotest5 = buildKotest5DescriptorFilter(launcherArgs)
81
86
82
- val console = TestEngineListenerBuilder .builder()
83
- .withType(
84
- launcherArgs[LISTENER ] ? : launcherArgs[REPORTER ] ? : launcherArgs[WRITER ]
85
- ) // sets the output type, will be detected if not specified
86
- .withTermColors(launcherArgs[TERMCOLORS ]) // if using the console, determines the prettiness of the output
87
- .build()
87
+ val outputListener = buildOutputTestEngineListener(launcherArgs)
88
88
89
89
// we want to collect the results, so we can check if we need exit with an error
90
90
val collector = CollectingTestEngineListener ()
@@ -93,7 +93,7 @@ fun main(args: Array<String>) {
93
93
CompositeTestEngineListener (
94
94
collector,
95
95
LoggingTestEngineListener ,// we use this to write to the kotest log file
96
- ThreadSafeTestEngineListener (PinnedSpecTestEngineListener (console ))
96
+ ThreadSafeTestEngineListener (PinnedSpecTestEngineListener (outputListener ))
97
97
)
98
98
).withClasses(classes)
99
99
.addExtensions(listOfNotNull(descriptorFilter, descriptorFilterKotest5))
@@ -107,3 +107,27 @@ fun main(args: Array<String>) {
107
107
// so we must force the exit
108
108
if (collector.errors) exitProcess(- 1 ) else exitProcess(0 )
109
109
}
110
+
111
+ private fun buildOutputTestEngineListener (launcherArgs : Map <String , String >): TestEngineListener {
112
+ return TestEngineListenerBuilder .builder()
113
+ .withType(
114
+ launcherArgs[ARG_LISTENER ] ? : launcherArgs[REPORTER ] ? : launcherArgs[WRITER ]
115
+ ) // sets the output type, will be detected if not specified
116
+ .withTermColors(launcherArgs[ARG_TERMCOLOR ]) // if using the console, determines the prettiness of the output
117
+ .build()
118
+ }
119
+
120
+ private fun buildDescriptorFilter (launcherArgs : Map <String , String >): ProvidedDescriptorFilter ? {
121
+ return launcherArgs[DESCRIPTOR ]?.let { descriptor ->
122
+ // println("Making a filter from input $descriptor")
123
+ ProvidedDescriptorFilter (DescriptorPaths .parse(descriptor))
124
+ }
125
+ }
126
+
127
+ private fun buildKotest5DescriptorFilter (launcherArgs : Map <String , String >): ProvidedDescriptorFilter ? {
128
+ return launcherArgs[TESTPATH ]?.let { test ->
129
+ launcherArgs[SPEC ]?.let { spec ->
130
+ ProvidedDescriptorFilter (DescriptorPaths .parse(" $spec /$test " ))
131
+ }
132
+ }
133
+ }
0 commit comments