Gradle:如何在控制台中实时显示测试结果?


231

我希望看到测试结果(system.out / err,记录来自正在测试的组件的消息),因为它们在我运行的同一控制台中运行:

gradle test

不要等到测试完成后再查看测试报告(这些报告仅在测试完成时生成,因此我无法在测试运行时“尾巴-f”任何内容)

Answers:


169

您可以在命令行上以INFO日志记录级别运行Gradle。它会向您显示每个测试运行时的结果。缺点是您还将获得更多其他任务的输出。

gradle test -i

13
使用1.0里程碑6,Gradle DSL现在让您直接在闭包内使用testLogging.showStandardStreams = true进行配置test
本杰明·穆奇科

4
这在gradle 1.11中不起作用。我得到了很多调试输出,但没有单独的测试结果。
David Moles 2014年

44
-i将在终端上抛出一堆不相关的信息。
2015年

9
除了大量无用的输出外,对于通过但不产生任何输出的测试,不会显示任何内容。

1
您可以grep用来过滤掉数千行。见stackoverflow.com/questions/3963708/...
MR-IDE

172

这是我喜欢的版本:

花式测试结果

import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent

tasks.withType(Test) {
    testLogging {
        // set options for log level LIFECYCLE
        events TestLogEvent.FAILED,
               TestLogEvent.PASSED,
               TestLogEvent.SKIPPED,
               TestLogEvent.STANDARD_OUT
        exceptionFormat TestExceptionFormat.FULL
        showExceptions true
        showCauses true
        showStackTraces true

        // set options for log level DEBUG and INFO
        debug {
            events TestLogEvent.STARTED,
                   TestLogEvent.FAILED,
                   TestLogEvent.PASSED,
                   TestLogEvent.SKIPPED,
                   TestLogEvent.STANDARD_ERROR,
                   TestLogEvent.STANDARD_OUT
            exceptionFormat TestExceptionFormat.FULL
        }
        info.events = debug.events
        info.exceptionFormat = debug.exceptionFormat

        afterSuite { desc, result ->
            if (!desc.parent) { // will match the outermost suite
                def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)"
                def startItem = '|  ', endItem = '  |'
                def repeatLength = startItem.length() + output.length() + endItem.length()
                println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength))
            }
        }
    }
}

13
我认为这是最好的答案。它包含最大的选项集,每个人都可以根据需要配置测试。
斯拉夫,

2
@sealskej我需要将此代码复制到哪里以及如何从命令行运行它?编辑:知道了-只需将其添加到模块的gradle.config中并正常运行
即可-hardysim

真好!我刚刚从中删除了这些管道|startItem因为通过Android Studio 2.2.3运行任务将其识别为消息中的错误,并且对成功构建很烦人。
madlymad

1
以及如何启用颜色?
杜尔加·斯瓦鲁普

1
@DurgaSwaroop为我开箱即用。请确保您的终端应用程序支持颜色。我个人使用iTerm2应用程序。
Shubham Chaudhary

156

您可以在build.gradle文件中添加一个Groovy闭包为您执行日志记录:

test {
    afterTest { desc, result -> 
        logger.quiet "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
    }
}

然后在您的控制台上显示如下:

:compileJava UP-TO-DATE
:compileGroovy
:processResources
:classes
:jar
:assemble
:compileTestJava
:compileTestGroovy
:processTestResources
:testClasses
:test
Executing test maturesShouldBeCharged11DollarsForDefaultMovie [movietickets.MovieTicketsTests] with result: SUCCESS
Executing test studentsShouldBeCharged8DollarsForDefaultMovie [movietickets.MovieTicketsTests] with result: SUCCESS
Executing test seniorsShouldBeCharged6DollarsForDefaultMovie [movietickets.MovieTicketsTests] with result: SUCCESS
Executing test childrenShouldBeCharged5DollarsAnd50CentForDefaultMovie [movietickets.MovieTicketsTests] with result: SUCCESS
:check
:build

从1.1版开始,Gradle支持更多选项来记录测试输出。使用这些选项,您可以通过以下配置获得类似的输出:

test {
    testLogging {
        events "passed", "skipped", "failed"
    }
}

4
这只会执行测试产生输出。我正在寻找的是在测试运行时查看日志记录/报告/系统输出/ printlns等。考虑使用maven或仅在IntelliJ / Eclipse中执行测试:输出是实时生成的。
tolitius

好的,很抱歉误解了您的问题。对于这种情况,您应该看一下Gradle文档的以下部分:gradle.org/logging.html#sec
stefanglase 2010年

1
那么,我实际进行哪些更改以查看输出?我在文档中看到了所有这些自定义侦听器和内容,但是我不知道如何配置它。
jpswain 2011年

118

正如stefanglase回答:

将以下代码添加到您的build.gradle(自1.1版开始)中,对于通过跳过失败的测试的输出效果很好。

test {
    testLogging {
        events "passed", "skipped", "failed", "standardOut", "standardError"
    }
}

我还要说的是(对于初学者来说这是一个问题),该gradle test命令每次更改仅执行一次测试。

因此,如果您第二次运行它,测试结果将不会输出。您还可以在建筑输出中看到这一点:gradle然后在测试中说UP-TO-DATE。因此,它没有执行第n次。

聪明的gradle!

如果要强制测试用例运行,请使用gradle cleanTest test

这是有点题外话,但我希望它将对一些新手有所帮助。

编辑

正如sparc_spread在评论中所述:

如果您想强制gradle 始终运行新的测试(可能并不总是一个好主意),可以添加outputs.upToDateWhen {false}testLogging { [...] }在这里继续阅读。

和平。


11
嘿,只是想让您知道,我找到了一种不必gradle cleanTest test每次都说的方法(自Gradle 1.12开始)。添加outputs.upToDateWhen {false}testLogging {...}和应该做的伎俩。它将迫使Gradle每次都运行测试。我在Dockter本人发布的Gradle论坛中找到了这个。希望这可以帮助。
sparc_spread 2014年

我将提供exceptionFormat "full"有关失败的详细信息,当您使用AssertJ或类似的lib时有用。
莎朗·托莱多

5
而不是cleanTest您可以使用test --rerun-tasks
Givenkoa

2
@gavenkoa我认为--rerun-tasks这将使您的所有任务重新运行,而不仅仅是测试任务。
ThomasW

2
实际上,cleanTest test在最新的Android Studio和gradle 3.3上,我无法正常工作,但--rerun-tasks确实成功了。不知道为什么。但是读完这个答案确实解决了我的头痛,在我添加完所有内容之后,测试日志记录在哪里?
Wingzero

111

免责声明:我是Gradle Test Logger插件的开发人员。

您可以简单地使用Gradle Test Logger插件在控制台上打印精美的日志。该插件使用合理的默认值来满足大多数用户的配置需求,甚至很少或没有配置,而且还提供了许多主题和配置选项以适合所有人。

例子

标准主题 标准主题

摩卡主题 摩卡主题

用法

plugins {
    id 'com.adarshr.test-logger' version '<version>'
}

确保始终从Gradle Central获得最新版本

组态

您根本不需要任何配置。但是,该插件提供了一些选项。可以执行以下操作(显示默认值):

testlogger {
    // pick a theme - mocha, standard, plain, mocha-parallel, standard-parallel or plain-parallel
    theme 'standard'

    // set to false to disable detailed failure logs
    showExceptions true

    // set to false to hide stack traces
    showStackTraces true

    // set to true to remove any filtering applied to stack traces
    showFullStackTraces false

    // set to false to hide exception causes
    showCauses true

    // set threshold in milliseconds to highlight slow tests
    slowThreshold 2000

    // displays a breakdown of passes, failures and skips along with total duration
    showSummary true

    // set to true to see simple class names
    showSimpleNames false

    // set to false to hide passed tests
    showPassed true

    // set to false to hide skipped tests
    showSkipped true

    // set to false to hide failed tests
    showFailed true

    // enable to see standard out and error streams inline with the test results
    showStandardStreams false

    // set to false to hide passed standard out and error streams
    showPassedStandardStreams true

    // set to false to hide skipped standard out and error streams
    showSkippedStandardStreams true

    // set to false to hide failed standard out and error streams
    showFailedStandardStreams true
}

希望您会喜欢使用它。


3
真好!令人惊讶的事情如通过/失败/跳过测试的摘要一样简单。
MarkHu

我只是集成了插件,但没有看到测试所需的时间,就像您的git中括号中的每个测试(1.6s)那样启用该功能?
dk7 '18年

@ dk7默认情况下,只有运行时间超过1秒的测试才会显示持续时间。请参阅文档以获取更多信息。如果要查看所有持续时间,只需将其设置slowThreshold0
adarshr

1
@ HaroldL.Brown的确是这样的:)我目前只是被一些东西淹没了,但它仍然很活跃。
adarshr

1
是@VadymTyemirov。一旦我将其记录下来,便与github.com/radarsh/gradle-test-logger-plugin/issues/137相同
adarshr

49

添加此选项可build.gradle阻止gradle吞咽stdout和stderr。

test {
    testLogging.showStandardStreams = true
}

它记录在这里


38

“测试”任务不适用于Android插件,对于Android插件,请使用以下命令:

// Test Logging
tasks.withType(Test) {
    testLogging {
        events "started", "passed", "skipped", "failed"
    }
}

请参阅以下内容:https : //stackoverflow.com/a/31665341/3521637


3
太棒了 仅供参考,我-不要将其放置在android {}块中来节省两分钟
Shubham Chaudhary

18

作为Shubham的一个很好的答案的后续,我建议使用枚举值而不是string。请查看TestLogging类文档

import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent

tasks.withType(Test) {
    testLogging {
        events TestLogEvent.FAILED,
               TestLogEvent.PASSED,
               TestLogEvent.SKIPPED,
               TestLogEvent.STANDARD_ERROR,
               TestLogEvent.STANDARD_OUT
        exceptionFormat TestExceptionFormat.FULL
        showCauses true
        showExceptions true
        showStackTraces true
    }
}

12

我最喜欢的简约版本基于Shubham Chaudhary的答案。 在此处输入图片说明

把它放在build.gradle文件中:

test {
    afterSuite { desc, result ->
    if (!desc.parent)
        println("${result.resultType} " +
            "(${result.testCount} tests, " +
            "${result.successfulTestCount} successes, " +
            "${result.failedTestCount} failures, " +
            "${result.skippedTestCount} skipped)")
    }
}

7

在使用Android插件的Gradle中:

gradle.projectsEvaluated {
    tasks.withType(Test) { task ->
        task.afterTest { desc, result ->
            println "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
        }
    }
}

然后输出将是:

执行测试testConversionMinutes [org.example.app.test.DurationTest],结果为:SUCCESS


3

Shubham的好答案JJD的合并使用枚举而不是字符串

tasks.withType(Test) {
   testLogging {
       // set options for log level LIFECYCLE
       events TestLogEvent.PASSED,
            TestLogEvent.SKIPPED, TestLogEvent.FAILED, TestLogEvent.STANDARD_OUT
       showExceptions true
       exceptionFormat TestExceptionFormat.FULL
       showCauses true
       showStackTraces true

    // set options for log level DEBUG and INFO
       debug {
        events TestLogEvent.STARTED, TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED, TestLogEvent.STANDARD_OUT, TestLogEvent.STANDARD_ERROR
        exceptionFormat TestExceptionFormat.FULL
       }
       info.events = debug.events
       info.exceptionFormat = debug.exceptionFormat

       afterSuite { desc, result ->
           if (!desc.parent) { // will match the outermost suite
               def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
               def startItem = '|  ', endItem = '  |'
               def repeatLength = startItem.length() + output.length() + endItem.length()
               println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength))
           }
       }
   }
}

2
我要求您围绕您的答案添加更多背景信息。仅代码或仅链接的答案很难理解。如果您可以在帖子中添加更多信息,它将对询问者和未来的读者都有帮助。
RBT

2

根据本杰明·穆奇科Benjamin Muschko)的回答(2011年3月19日),您可以将-i标志与grep一起使用,以过滤掉数千行不需要的行。例子:

强过滤器 -仅显示每个单元测试名称和结果以及整体构建状态。安装程序错误或异常不会显示。

./gradlew test -i | grep -E " > |BUILD"

软过滤器 -显示每个单元测试名称和结果,以及设置错误/异常。但它还将包含一些不相关的信息:

./gradlew test -i | grep -E -v "^Executing |^Creating |^Parsing |^Using |^Merging |^Download |^title=Compiling|^AAPT|^future=|^task=|:app:|V/InstrumentationResultParser:"

软过滤器,替代语法:(搜索令牌被拆分为单个字符串)

./gradlew test -i | grep -v -e "^Executing " -e "^Creating " -e "^Parsing " -e "^Using " -e "^Merging " -e "^Download " -e "^title=Compiling" -e "^AAPT" -e "^future=" -e "^task=" -e ":app:" -e "V/InstrumentationResultParser:"

解释其工作方式:第一个命令的输出通过./gradlew test -i管道传递给第二个命令grep,第二个命令将基于正则表达式过滤掉许多不需要的行。"-E"启用正则表达式模式,并"|"表示“或”。可以使用显示单元测试名称和结果" > ",并使用允许总体状态"BUILD"。在软过滤器中,"-v"标志的意思是“不包含”"^"意思是“行的开始”。因此,它会删除所有以“正在执行”开头或以“正在创建”开头的行,等等。


带有gradle 5.1的Android工具单元测试示例:

./gradlew connectedDebugAndroidTest --continue -i | grep -v -e \
"^Transforming " -e "^Skipping " -e "^Cache " -e "^Performance " -e "^Creating " -e \
"^Parsing " -e "^file " -e "ddms: " -e ":app:" -e "V/InstrumentationResultParser:"

带有gradle 4.10的Jacoco单元测试覆盖范围示例:

./gradlew createDebugCoverageReport --continue -i | grep -E -v "^Executing |^Creating |^Parsing |^Using |^Merging |^Download |^title=Compiling|^AAPT|^future=|^task=|:app:|V/InstrumentationResultParser:"

0

如果您是build.gradle.ktsKotlin DSL编写的,则可以使用以下命令打印测试结果(我正在开发一个kotlin跨平台项目,未应用“ java”插件):

tasks.withType<AbstractTestTask> {
    afterSuite(KotlinClosure2({ desc: TestDescriptor, result: TestResult ->
        if (desc.parent == null) { // will match the outermost suite
            println("Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)")
        }
    }))
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.