I'm using Timber with a DebugTree
and a ProductionTree
. All is fine and perfect in the running app.
I also succeed to use Timber in my JUnit test implementation, and that's fine (no real benefit, but it does work).
However, I would like to get the logs on the code under test
to be displayed in the JUnit log.
I tried to build a JUnitTree
and redirect timber logs to println(…)
, and setup the Timber JUnitTree
in @Before
function, but nothing worked. Any solution from the community?
Does my request make no sens, I didn't find anything about this need in the web (maybe I used wrong keywords).
The following ConsoleTree
class can be used to forward Timber logs to standard output:
class ConsoleTree : Timber.DebugTree() {
@Language("RegExp")
private val anonymousClassPattern = Pattern.compile("""(\$\d+)+$""")
private val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
val dateTime = LocalDateTime.now().formatWith(dateTimeFormatter)
val priorityChar = when (priority) {
Log.VERBOSE -> 'V'
Log.DEBUG -> 'D'
Log.INFO -> 'I'
Log.WARN -> 'W'
Log.ERROR -> 'E'
Log.ASSERT -> 'A'
else -> '?'
}
println("$dateTime $priorityChar/$tag: $message")
}
override fun createStackElementTag(element: StackTraceElement): String? {
val matcher = anonymousClassPattern.matcher(element.className)
val tag = when {
matcher.find() -> matcher.replaceAll("")
else -> element.className
}
return tag.substringAfterLast('.')
}
}
For JUnit 4 a rule can be used to plant and uproot ConsoleTree
automatically for each test:
class TimberConsoleRule : TestRule {
override fun apply(base: Statement, description: Description) =
TimberConsoleStatement(base)
}
class TimberConsoleStatement constructor(private val baseStatement: Statement) : Statement() {
private val consoleTree = ConsoleTree()
override fun evaluate() {
Timber.plant(consoleTree)
try {
baseStatement.evaluate()
} finally {
Timber.uproot(consoleTree)
}
}
}
For JUnit 5 you can simply annotate JUnit test with the following @TimberConsoleLog
annotation:
@ExtendWith(TimberConsoleExtension::class)
@Retention(RUNTIME)
annotation class TimberConsoleLog
class TimberConsoleExtension : BeforeAllCallback, AfterAllCallback {
private val consoleTree = ConsoleTree()
override fun beforeAll(context: ExtensionContext) =
Timber.plant(consoleTree)
override fun afterAll(context: ExtensionContext) =
Timber.uproot(consoleTree)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With