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

我想看测试结果(系统)。out/err,日志消息来自正在测试的组件)当他们奔跑时在同一个控制台我运行:

gradle test

不要等到测试完成才查看测试报告(测试报告仅在测试完成时生成,因此在运行测试时不能“尾部-f”任何内容)

190249 次浏览

您可以在构建中添加Groovy闭包。Gradle文件,为您做日志记录:

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"
}
}

你可以在命令行上使用INFO日志级别运行Gradle。它将在运行时显示每个测试的结果。缺点是其他任务的输出也会多得多。

gradle test -i

As stefanglase回答:

将以下代码添加到你的build.gradle(自版本1.1起),可以很好地输出通过了跳过失败的测试。

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

另外,我想说的是(我发现这对初学者来说是一个问题)gradle test命令执行测试每次更改只需要一次

所以如果你正在运行它第二次将没有测试结果的输出。你也可以在建筑输出中看到这一点:gradle然后在测试中说最新的。所以它不是第n次执行。

聪明的它!

如果你想强迫测试用例运行,使用gradle cleanTest test

这有点离题,但我希望它能帮助到一些新手。

编辑

正如sparc_spread在评论中所述:

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

和平。

将此添加到build.gradle以阻止gradle吞咽stdout和stderr。

test {
testLogging.showStandardStreams = true
}

它被记录为在这里

'test'任务不适用于Android插件,对于Android插件使用以下方法:

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

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

在Gradle使用Android插件:

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]。结果为SUCCESS

以下是我的观点:

fancy test result

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

作为Shubham的回答很好的后续,我建议使用枚举值而不是字符串。请看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
}
}

Shubham的回答很好JJD使用enum代替string的合并

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))
}
}
}
}
我最喜欢的基于Shubham Chaudhary答案的简约版本。 enter image description here < / p >

将此放在build.gradle文件中:

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

免责声明:我是Gradle Test Logger Plugin的开发者。

你可以简单地使用Gradle测试记录器插件在控制台上打印漂亮的日志。该插件使用合理的默认值,以满足大多数用户很少或没有配置,但也提供了许多主题和配置选项,以满足每个人。

例子

Standard Theme 标准主题< / p >

摩卡主题 摩卡主题< / p >

使用

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
}

我希望你会喜欢使用它。

本杰明·穆什科的回答(2011年3月19日)之后,你可以使用-i标志和grep一起过滤掉1000个不需要的行。例子:

强大的过滤 -只显示每个单元测试名称和测试结果以及整体构建状态。设置错误或异常不显示。

./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"-i"表示“信息/详细”;模式,该模式实时打印每个测试的结果,但也显示大量不需要的调试行。

因此,第一个命令./gradlew test -i的输出被输送到第二个命令grep,该命令将根据正则表达式过滤掉许多不需要的行。"-E"为单个字符串启用正则表达式模式;"-e"为多个字符串启用正则表达式;而"|"在正则表达式字符串中表示"或"。

在强过滤器中,允许使用" > "显示单元测试名称和测试结果,并且允许使用"BUILD"显示整体状态。

在软过滤器中,"-v"标志表示“不是containing",而"^"表示“行开始”。因此,它删除了所有以“执行”开头的行;或者以“创造”开头,等等。


Android仪器仪表单元测试的例子,使用gradle 5.1:

./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:"

如果你有一个用芬兰湾的科特林DSL编写的build.gradle.kts,你可以用(我正在开发一个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)")
}
}))
}

只需将以下闭包添加到build.gradle中。每次测试执行之后,输出都会被打印出来。

test{
useJUnitPlatform()
afterTest { desc, result ->
def output = "Class name: ${desc.className}, Test name: ${desc.name},  (Test status: ${result.resultType})"
println( '\n' + output)
}
}

对于那些使用Kotlin DSL的用户,你可以这样做:

tasks {
named<Test>("test") {
testLogging.showStandardStreams = true
}
}

如果你正在使用jupiter,没有一个答案工作,请考虑验证它是否正确设置:

test {
useJUnitPlatform()
outputs.upToDateWhen { false }
}


dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

然后试试那些公认的答案

对于Android,这很有效:

android {
...


testOptions {
unitTests.all {
testLogging {
outputs.upToDateWhen { false }
events "passed", "failed", "skipped", "standardError"
showCauses true
showExceptions true
}
}
}

看到从控制台运行Android单元/检测测试

对于那些使用Kotlin DSL的人来说,一个更全面的回应是:

subprojects {
// all the other stuff
// ...
tasks.named<Test>("test") {
useJUnitPlatform()
setupTestLogging()
}
}


fun Test.setupTestLogging() {
testLogging {
events(
org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED,
org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED,
org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED,
org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_OUT,
)
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
showExceptions = true
showCauses = true
showStackTraces = true


addTestListener(object : TestListener {
override fun beforeSuite(suite: TestDescriptor) {}
override fun beforeTest(testDescriptor: TestDescriptor) {}
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {}
override fun afterSuite(suite: TestDescriptor, result: TestResult) {
if (suite.parent != null) { // will match the outermost suite
val output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)"
val startItem = "|  "
val endItem = "  |"
val repeatLength = startItem.length + output.length + endItem.length
val messages = """
${(1..repeatLength).joinToString("") { "-" }}
$startItem$output$endItem
${(1..repeatLength).joinToString("") { "-" }}
""".trimIndent()
println(messages)
}
}
})
}
}

这应该产生一个接近@odemolliens answers的输出。

我为Kotlin DSL编写了一个测试记录器。你可以把这个块放在你的项目范围build.gradle.kts文件中。

subprojects {
tasks.withType(Test::class.java) {
testLogging {
showCauses = false
showExceptions = false
showStackTraces = false
showStandardStreams = false


val ansiReset = "\u001B[0m"
val ansiGreen = "\u001B[32m"
val ansiRed = "\u001B[31m"
val ansiYellow = "\u001B[33m"


fun getColoredResultType(resultType: ResultType): String {
return when (resultType) {
ResultType.SUCCESS -> "$ansiGreen $resultType $ansiReset"
ResultType.FAILURE -> "$ansiRed $resultType $ansiReset"
ResultType.SKIPPED -> "$ansiYellow $resultType $ansiReset"
}
}


afterTest(
KotlinClosure2({ desc: TestDescriptor, result: TestResult ->
println("${desc.className} | ${desc.displayName} = ${getColoredResultType(result.resultType)}")
})
)


afterSuite(
KotlinClosure2({ desc: TestDescriptor, result: TestResult ->
if (desc.parent == null) {
println("Result: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)")
}
})
)
}
}
}

enter image description here