com.github.yag.punner.core.TestingServer.kt Maven / Gradle / Ivy
Go to download
Punner is a parallel JUnit test runner and maven plugin which can speed up your unit test.
package com.github.yag.punner.core
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
import org.junit.BeforeClass
import org.junit.ComparisonFailure
import org.junit.runners.model.FrameworkMethod
import org.junit.runners.model.TestClass
import java.io.File
import java.io.ObjectOutputStream
import java.lang.AssertionError
internal object TestingServer {
private val classInstanceCache = HashMap, Any>()
@JvmStatic
fun main(args: Array) {
val delimiter = args[0]
System.`in`.bufferedReader().lines().forEach {
runCommand(it, delimiter)
}
shutdown()
}
internal fun shutdown() {
classInstanceCache.forEach { t, _ ->
val afterClass = TestClass(t).getAnnotatedMethods(AfterClass::class.java)
afterClass.forEach {
it.invokeExplosively(null)
}
}
}
@Suppress("UNCHECKED_CAST")
internal fun getInstance(clazz: Class): T {
var instance = classInstanceCache[clazz]
return if (instance == null) {
clazz.newInstance().apply {
classInstanceCache[clazz] = this as Any
val beforeClass = TestClass(clazz).getAnnotatedMethods(BeforeClass::class.java)
beforeClass.forEach {
it.invokeExplosively(null)
}
}
} else {
instance as T
}
}
private fun runCommand(command: String, delimiter: String) : TestResultStore {
val parameters = command.split(" ")
// This file only used for test result passing, no log data.
val (className, methodName, resultPath) = parameters
val resultOutput = ObjectOutputStream(File(resultPath).outputStream())
val clazz = Class.forName(className)
val result = test(clazz, methodName, delimiter)
result.write(resultOutput)
resultOutput.flush()
resultOutput.close()
println(magicFinish(delimiter))
System.out.flush()
return result
}
internal fun test(clazz: Class<*>, methodName: String, delimiter: String) : TestResultStore {
val props = System.getProperties()
var after: List? = null
var instance: Any? = null
try {
instance = getInstance(clazz)
val testClass = TestClass(clazz)
val before = testClass.getAnnotatedMethods(Before::class.java)
after = testClass.getAnnotatedMethods(After::class.java)
val method = FrameworkMethod(clazz.getMethod(methodName))
before.forEach { it.invokeExplosively(instance) }
println(magicStart(delimiter))
method.invokeExplosively(instance)
return TestResultStore(ResultType.SUCCESS, NoError, props)
} catch (e: Throwable) {
return TestResultStore(getResultType(e), e, props)
} finally {
after?.forEach { method ->
instance?.let { instance ->
method.invokeExplosively(instance)
}
}
}
}
}
/**
* Get result type by exception.
* @param e exception
*/
fun getResultType(e: Throwable): ResultType {
return when (e) {
is AssertionError, is ComparisonFailure -> ResultType.FAILURE
else -> ResultType.ERROR
}
}