Gradle:如何在控制台中实时显示测试结果?
Posted
技术标签:
【中文标题】Gradle:如何在控制台中实时显示测试结果?【英文标题】:Gradle: How to Display Test Results in the Console in Real Time? 【发布时间】:2011-04-27 04:41:59 【问题描述】:我想在我运行的同一个控制台中看到测试结果(system.out/err,来自被测试组件的日志消息):
gradle test
不要等到测试完成后再查看测试报告(仅在测试完成时生成,所以在测试运行时我不能“tail -f”任何东西)
【问题讨论】:
另请参阅***.com/questions/45856846/…,了解通过初始化脚本添加测试输出的示例,以便任何项目都可以免费获得它。 【参考方案1】:我为 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)")
)
)
【讨论】:
【参考方案2】:为使用 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 答案的输出。
【讨论】:
【参考方案3】:对于 android,这很好用:
android
...
testOptions
unitTests.all
testLogging
outputs.upToDateWhen false
events "passed", "failed", "skipped", "standardError"
showCauses true
showExceptions true
见Running Android unit / instrumentation tests from the console
【讨论】:
【参考方案4】:从 Benjamin Muschko's answer(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
,"-i"
表示“信息/详细”模式,实时打印每个测试的结果,但也显示大量不需要的调试行。
所以第一个命令./gradlew test -i
的输出通过管道传送到第二个命令grep
,它将根据正则表达式过滤掉许多不需要的行。 "-E"
为单个字符串启用正则表达式模式; "-e"
启用多个字符串的正则表达式;而正则表达式字符串中的"|"
表示“或”。
在强过滤器中,允许使用" > "
显示单元测试名称和测试结果,使用"BUILD"
允许显示整体状态。
在软过滤器中,"-v"
标志表示"not containing","^"
表示“行首”。所以它会去掉所有以“Executing”开头的行或以“Creating”开头的行,等等。
带有 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:"
Jacoco 单元测试覆盖率示例,使用 gradle 4.10:
./gradlew createDebugCoverageReport --continue -i | grep -E -v "^Executing |^Creating |^Parsing |^Using |^Merging |^Download |^title=Compiling|^AAPT|^future=|^task=|:app:|V/InstrumentationResultParser:"
【讨论】:
这里还有一个建议,如果您只对测试结果感兴趣:...grep -e "^.*\..*\..*>.*\[.*\].*"
for output of 'com.your.package.. > test_check_correct[AVD_NAME] SUCCESS' only . (或...grep -e "^.*\..*\..*>.*\[.*\].*\|^> Task :.*"
还包括 > Task :app:mergeDexMinApi14Debug 行)【参考方案5】:
如果您使用的是 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'
然后尝试接受的答案
【讨论】:
【参考方案6】:对于那些使用 Kotlin DSL 的人,你可以这样做:
tasks
named<Test>("test")
testLogging.showStandardStreams = true
【讨论】:
【参考方案7】:只需将以下闭包添加到您的 build.gradle。每次测试执行后都会打印输出。
test
useJUnitPlatform()
afterTest desc, result ->
def output = "Class name: $desc.className, Test name: $desc.name, (Test status: $result.resultType)"
println( '\n' + output)
【讨论】:
Could not find method test() for arguments
... 你把这个闭包放在哪里?以及哪个 build.gradle 文件?【参考方案8】:
如果你有一个用 Kotlin 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)")
))
【讨论】:
您是否通过命令行使用./gradlew test
之类的内容调用了此任务?我试过了,但通过命令行调用时没有看到任何输出。
是的,我正在使用命令行调用此任务。在撰写我的答案时,这正在使用 gradle 版本......现在该项目不再受我的控制,我不知道 mantainers 做了什么。对不起。【参考方案9】:
免责声明:我是 Gradle Test Logger 插件的开发者。
您可以简单地使用Gradle Test Logger Plugin 在控制台上打印漂亮的日志。该插件使用合理的默认值来满足大多数用户只需很少或没有配置,但还提供了许多主题和配置选项以适合每个人。
示例
标准主题
摩卡主题
用法
plugins
id 'com.adarshr.test-logger' version '<version>'
确保您始终收到latest version from 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
我希望你会喜欢使用它。
【讨论】:
不错!通过/失败/跳过的测试的总结如此简单的事情导致了它。 我刚刚集成了插件,但我没有看到测试的持续时间,就像在你的 git 中括号中的每个测试一样(1.6s)如何启用它? @HaroldL.Brown 确实是 :) 我现在只是有点忙于一些事情,但它非常活跃。 是的@VadymTyemirov。与github.com/radarsh/gradle-test-logger-plugin/issues/137 相同,一旦我记录了它? 对于多模块项目添加到根 build.gradle: plugins id 'com.adarshr.test-logger' version '2.1.0' subprojects apply plugin: 'com.adarshr.test-记录器'【参考方案10】:这是我喜欢的版本:
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))
【讨论】:
在我看来,这是最好的答案。它包含最大的选项集,每个人都可以根据需要配置他们的测试。 @sealskej 我需要将此代码复制到哪里以及如何从命令行运行它?编辑:知道了 - 只需将其添加到模块的 gradle.config 并正常运行 你是如何启用颜色的? @DurgaSwaroop 对我来说开箱即用。请确保您的终端应用程序支持颜色。我个人使用 iTerm2 应用程序。 使用 Gradle 4.5 就像一个魅力【参考方案11】:您可以在 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 支持很多 more options to log test output。有了这些选项,您可以通过以下配置实现类似的输出:
test
testLogging
events "passed", "skipped", "failed"
【讨论】:
这只会在测试执行后产生输出。我正在寻找的是查看日志记录/报告/系统输出/printlns 等。因为测试正在运行。考虑使用 maven 或仅在 IntelliJ / Eclipse 中执行测试:输出是实时生成的。 好的,很抱歉误解了您的问题。对于这种情况,您应该查看 Gradle 文档的以下部分:gradle.org/logging.html#sec:external_tools 那么我实际上做了什么改变才能看到输出?我在文档中看到了所有这些自定义侦听器和东西,但我不知道如何配置它。【参考方案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)")
【讨论】:
【参考方案13】:合并Shubham's great answer 和JJD use enum instead of 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))
【讨论】:
我请求您为您的答案添加更多上下文。仅代码或仅链接的答案很难理解。如果您可以在帖子中添加更多信息,这将对提问者和未来的读者都有帮助。【参考方案14】:作为Shubham's great answer 的后续行动,我建议使用enum 值而不是strings。请看documentation of the TestLogging class。
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
【讨论】:
【参考方案15】:正如 stefanglase 回答的那样:
将以下代码添加到您的 build.gradle
(从 1.1 版开始)对于 passed、skipped 和 failed 测试的输出效果很好。
test
testLogging
events "passed", "skipped", "failed", "standardOut", "standardError"
我想补充一点(我发现这对初学者来说是个问题)是gradle test
命令每次更改只执行一次测试。
因此,如果您第二次运行它,测试结果将不会有任何输出。您还可以在构建输出中看到这一点:gradle 然后在测试中说 UP-TO-DATE。所以它没有执行第n次。
智能毕业!
如果您想强制测试用例运行,请使用gradle cleanTest test
。
这有点离题,但我希望它可以帮助一些新手。
编辑
正如 sparc_spread 在 cmets 中所述:
如果您想强制 gradle 始终运行新测试(这可能并不总是一个好主意),您可以将 outputs.upToDateWhen false
添加到 testLogging [...]
。继续阅读here。
和平。
【讨论】:
嘿,只是想让你知道,我找到了一种不必每次都说gradle cleanTest test
的方法(从 Gradle 1.12 开始)。将outputs.upToDateWhen false
添加到testLogging ...
就可以了。它将强制 Gradle 每次都运行测试。我找到了这个in the Gradle forums, posted by Dockter himself。希望这会有所帮助。
我会包含 exceptionFormat "full"
以获取有关失败的详细信息,这在您使用 AssertJ 或类似库时很有用。
你可以用test --rerun-tasks
代替cleanTest
@gavenkoa 我认为--rerun-tasks
会让你的所有任务重新运行,而不仅仅是测试任务。
实际上,最新的 Android Studio 和 gradle 3.3 上的 cleanTest test
对我不起作用,但 --rerun-tasks
成功了。不知道为什么。但是看了这个答案确实解决了我的头疼问题,我添加了所有东西之后的f**king测试记录在哪里。【参考方案16】:
将此添加到 build.gradle
以阻止 gradle 吞下 stdout 和 stderr。
test
testLogging.showStandardStreams = true
记录在案here。
【讨论】:
? 对于任何 Kotlin 人来说,我认为是val test by tasks.getting(Test::class) testLogging.showStandardStreams = true
。【参考方案17】:
'test' 任务不适用于 Android 插件,对于 Android 插件,请使用以下内容:
// Test Logging
tasks.withType(Test)
testLogging
events "started", "passed", "skipped", "failed"
请参阅以下内容:https://***.com/a/31665341/3521637
【讨论】:
太棒了。仅供参考,未来的我 - 不要将其放在 android 块中,从而节省您的两分钟【参考方案18】:在 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.DurationTest] 结果:SUCCESS
【讨论】:
【参考方案19】:您可以在命令行上使用 INFO 日志记录级别运行 Gradle。它会在运行时向您显示每个测试的结果。缺点是您还将获得更多其他任务的输出。
gradle test -i
【讨论】:
这在 gradle 1.11 中不起作用。我得到了很多调试输出,但不是个别的测试结果。 那个-i
会在终端上抛出一堆不相关的信息。
除了很多无用的输出外,没有任何输出的测试通过并没有显示任何内容。
您可以使用grep
过滤掉成千上万不需要的行。见***.com/questions/3963708/…以上是关于Gradle:如何在控制台中实时显示测试结果?的主要内容,如果未能解决你的问题,请参考以下文章