Как перенаправить журналы Timber на Junit logcat - PullRequest
1 голос
/ 21 марта 2020

Я использую Timber с DebugTree и ProductionTree. Все отлично и отлично работает в запущенном приложении. Мне также удается использовать Timber в моей реализации теста JUnit, и это нормально (никакой реальной выгоды, но это работает).

Однако я хотел бы, чтобы журналы на code under test отображались в журнал JUnit.

Я пытался создать JUnitTree и перенаправить журналы древесины на println(…) и настроить функцию Timber JUnitTree в @Before, но ничего не получалось. Любое решение от сообщества?

Мой запрос не имеет смысла, я ничего не нашел в сети (возможно, я использовал неправильные ключевые слова).

1 Ответ

1 голос
/ 30 марта 2020

Следующий класс ConsoleTree может использоваться для пересылки журналов Timber на стандартный вывод:

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('.')
    }
}

Для JUnit 4 может использоваться правило для установки и повышения root ConsoleTree автоматически для каждого 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)
        }
    }
}

Для JUnit 5 вы можете просто аннотировать JUnit test следующей @TimberConsoleLog аннотацией:

@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)
}
...