Test runner: Report stacktraces for failed tests in TC messages

This commit is contained in:
Ilya Matveev
2019-04-10 18:32:07 +07:00
committed by Ilya Matveev
parent 43c6452575
commit 25b2ec8366
3 changed files with 26 additions and 17 deletions
+21 -12
View File
@@ -33,24 +33,33 @@ public open class Throwable(open val message: String?, open val cause: Throwable
public fun getStackTrace(): Array<String> = stackTraceStrings public fun getStackTrace(): Array<String> = stackTraceStrings
public fun printStackTrace() { public fun printStackTrace(): Unit = dumpStackTrace { println(it) }
println(this.toString())
for (element in stackTraceStrings) { internal fun dumpStackTrace(): String = buildString {
println(" at $element") dumpStackTrace { appendln(it) }
}
private inline fun writeStackTraceElements(throwable: Throwable, writeln: (String) -> Unit) {
for (element in throwable.stackTraceStrings) {
writeln(" at $element")
} }
this.cause?.printEnclosedStackTrace(this)
} }
@Suppress("UNUSED_PARAMETER") private inline fun dumpStackTrace(crossinline writeln: (String) -> Unit) {
private fun printEnclosedStackTrace(enclosing: Throwable) { writeln(this@Throwable.toString())
// TODO: should skip common stack frames
print("Caused by: ") writeStackTraceElements(this, writeln)
this.printStackTrace()
var cause = this.cause
while (cause != null) {
// TODO: should skip common stack frames
writeln("Caused by: $cause")
writeStackTraceElements(cause, writeln)
cause = cause.cause
}
} }
override public fun toString(): String { public override fun toString(): String {
val kClass = this::class val kClass = this::class
val s = kClass.qualifiedName ?: kClass.simpleName ?: "Throwable" val s = kClass.qualifiedName ?: kClass.simpleName ?: "Throwable"
return if (message != null) s + ": " + message.toString() else s return if (message != null) s + ": " + message.toString() else s
@@ -51,9 +51,9 @@ internal class TeamCityLogger : BaseTestLogger() {
override fun pass(testCase: TestCase, timeMillis: Long) = finish(testCase, timeMillis) override fun pass(testCase: TestCase, timeMillis: Long) = finish(testCase, timeMillis)
override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) { override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) {
// TODO: Add 'details=...' command with the stack trace (need to implement stacktrace dumping as a string) val stackTrace = e.dumpStackTrace().escapeForTC()
e.printStackTrace() val message = e.message?.escapeForTC()
report("testFailed name='${testCase.tcName}' message='${e.message?.escapeForTC()}'") report("testFailed name='${testCase.tcName}' message='$message' details='$stackTrace'")
finish(testCase, timeMillis) finish(testCase, timeMillis)
} }
@@ -89,7 +89,7 @@ public abstract class BaseClassSuite<INSTANCE, COMPANION>(name: String, ignored:
} }
} }
// These two methods are overrided in test suite classes generated by the compiler. // These two methods are overridden in test suite classes generated by the compiler.
abstract fun createInstance(): INSTANCE abstract fun createInstance(): INSTANCE
open fun getCompanion(): COMPANION = throw NotImplementedError("Test class has no companion object") open fun getCompanion(): COMPANION = throw NotImplementedError("Test class has no companion object")