Heya :wave: I'm looking into building a tool to better-integrate test frameworks, just to see if its...
g
Heya šŸ‘‹ I'm looking into building a tool to better-integrate test frameworks, just to see if its possible. The current state seems to be implementing a tool specific testing interface (Maven/Gradle/IDEA/SBT/etc). The best thought I currently have, is to just use an interface around running
.jar
files. • JUnit5 has the
ConsoleLauncher
under
junit-platform-console-standalone
• Kotest has
KotestEngineLauncher
under
io.kotest.engine.launcher.MainKt
• I think other frameworks also have standalone
.jar
launchers which can discover and run + report tests, given some set of CLI args My question is around how exactly the Kotest one works/how to use it. I wasn't able to find very much documentation on it -- only by digging through code:
Copy code
data class LauncherArgs(
   // A path to the test to execute. Nested tests will also be executed
   val testpath: String?,
   // restricts tests to the package or subpackages
   val packageName: String?,
   // the fully qualified name of the spec class which contains the test to execute
   val spec: String?,
   // true to force true colour on the terminal; auto to have autodefault
   val termcolor: String?,
   // the fully qualified name of a reporter implementation
   val reporter: String?,
   // Tag expression to control which tests are executed
   val tagExpression: String?,
   // true to output the configuration values when the Engine is created
   val dumpconfig: Boolean?
)
Is there a guide anywhere on how someone interested in make a process-based wrapper for Kotest would go about it? And perhaps a bit unrelated, is this even a good idea?
s
It's how the intellij plugin works, so you could look at that to see how it's used. It's certainly fine to build on because the contract is fixed (because of the plugin).
g
@sam Appreciate the reply! This is going to be a dumb question, so pardon in advance: How exactly do you run the launcher? I've tried:
Copy code
$ java -jar kotest-runner-junit5-jvm-4.6.1.jar
no main manifest attribute, in kotest-runner-junit5-jvm-4.6.1.jar

$ java --module kotest-framework-launcher-4.2.0.module/io.kotest.engine.launcher.MainKt
Error occurred during initialization of boot layer
java.lang.module.FindException: Module kotest-framework-launcher-4.2.0.module not found
s
There's no runnable jar. It's used from other code.
I guess we could package one up that's runnable
so you can do the java -jar thing
g
Ohhh šŸ¤¦ā€ā™‚ļø I got the impression that the Gradle and Intellij extensions were somehow calling out to a
.jar
and passing args
Possible there's a way I can figure out to pass some flags to
java -jar
to tell it to run a specific class/method maybe
s
they invoke the launcher because they know its already on teh classpath by virtue of the fact you need the jars in order to use testtypes from kotest
g
Copy code
// <https://github.com/kotest/kotest-gradle-plugin/blob/2301c432a3b320c8683fe28972aa68c57f31ce66/src/main/kotlin/io/kotest/gradle/Kotest.kt>
//
private fun exec(classpath: FileCollection): JavaExecAction {
  val exec = DefaultExecActionFactory.of(fileResolver, fileCollectionFactory, executorFactory, null).newJavaExecAction()
  copyTo(exec)

  exec.main = "io.kotest.engine.launcher.MainKt"
  exec.classpath = classpath
  exec.jvmArgs = allJvmArgs
  exec.args = args()
  // this must be true so we can handle the failure ourselves by throwing GradleException
  // otherwise we get a nasty stack trace from gradle
  exec.isIgnoreExitValue = true

  return exec
}
Ahh so it needs to be put on the classpath
s
we could make a
kotest-framework-engine-launcher
module that just calls the launcher from a main method
or maybe you can do what you said, -jar and tell it which method/class to use
g
Ahh yes, I see the problem =/
Copy code
$ java -cp ./kotest/kotest-framework-engine-jvm-4.6.1.jar io.kotest.engine.launcher.MainKt -h
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
        at io.kotest.engine.launcher.MainKt.main(main.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:636)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:182)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519)
        ... 1 more
It would need to be an "Uberjar" or whatever they call them, that contains all sub-dependencies in it I think The
.module
file that comes with it also describes the required dependencies right?
s
yep a fat jar
which that other module I suggested could be
I assume you would also need to point it to where the test classes are, I guess that's how the junit one works
g
Well, I learned something new today! This would mean my grand idea wouldn't work so well unless the test frameworks have a "Fat Jar" launcher eh? =/
(I still think the launcher is a good idea FWIW)
s
The junit one is probably already stand alone
it won't have many dependencies like kotest has
kotest needs the kotlin std lib, the kotlin coroutines lib, and the engine itself
we can make a fat jar very easily
šŸ™ 1
šŸ™Œ 1
If you create a ticket we can work on it
g
šŸ‘šŸ» 1