Gradle: Як відображати результати тестів на консолі в режимі реального часу?


231

Я хотів би бачити результати тестування (system.out / err, повідомлення журналу з компонентів, які тестуються), коли вони працюють у тій же консолі, яку я запускаю:

gradle test

І не чекати, поки будуть проведені тести, щоб переглянути тестові звіти (які генеруються лише після завершення тестів, тому я не можу нічого "хвіст -f" під час запуску тестів)

Відповіді:


169

Ви можете запустити Gradle з рівнем журналу INFO в командному рядку. Він покаже вам результат кожного тесту під час їх запуску. Недоліком є ​​те, що ви отримаєте набагато більше результатів для інших завдань.

gradle test -i

13
Завдяки 1,0- мільній версії 6 Gradle DSL тепер дозволить вам налаштувати це безпосередньо, використовуючи testLogging.showStandardStreams = вірно в межах testзакриття.
Бенджамін Мушко

4
Це не працює в класі 1.11. Я отримую багато результатів налагодження, але не окремі результати тесту.
Девід Молес

44
Це -iкине купу невідповідних інформацій на термінал.
Чт Трінь

9
Окрім безлічі марних результатів, нічого не відображається для тестів, які проходять і не дають результатів.
toolbear

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 куди мені потрібно скопіювати цей код і як запустити його з командного рядка? EDIT: отримано - просто додайте його до gradle.config модулів і працюйте нормально
hardysim

Приємно! Я тільки що видалили труби |з startItemтому , що запуск завдання з допомогою Android Studio 2.2.3 розпізнає їх як помилки в повідомленнях , і це було прикро на успіх будує.
madlymad

1
І як ви включили кольори?
Durga Swaroop

1
@DurgaSwaroop для мене працює з коробки. Переконайтеся, що ваш термінальний додаток підтримує кольори. Я особисто використовую додаток iTerm2.
Shubham Chaudhary

156

Ви можете додати закритий засіб Groovy у свій файл build.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"
    }
}

4
це дасть результат лише після виконання тесту. Що я шукаю - це бачити журнал / звітування / системні виходи / printlns тощо. під час запуску тестів . подумайте про виконання тестів з maven або просто в IntelliJ / Eclipse: вихід виробляється в режимі реального часу.
толітій

Гаразд, вибачте за нерозуміння вашого питання. У цьому випадку вам слід ознайомитися з наступною частиною документації Gradle: gradle.org/logging.html#sec:external_tools
stefanglase

1
Отже, які зміни я насправді вношу, щоб побачити вихід? Я бачу всі ці користувальницькі слухачі та речі в документації, але не маю уявлення, як це налаштувати.
jpswain

118

Як відповіла стефанглаза :

додавання наступного коду до вашого build.gradle(оскільки версія 1.1) працює чудово для виведення на пройдені , пропущені та невдалі тести.

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

Що я хочу сказати додатково (я з’ясував, що це проблема для початківців) - це те, що gradle testкоманда виконує тест лише один раз за зміну .

Тож якщо ви будете запускати його вдруге, результатів тестування не буде . Ви також можете побачити це у виході будівлі: gradle потім каже UP-TO-DATE на тестах. Тож її не виконували n-го разу.

Розумний градул!

Якщо ви хочете змусити запускати тестові справи, використовуйте gradle cleanTest test.

Це трохи поза темою, але я сподіваюся, що це допоможе новачкам.

редагувати

Як зазначено в коментарях sparc_spread :

Якщо ви хочете змусити gradle завжди виконувати нові тести (що може не завжди бути хорошою ідеєю), ви можете додати outputs.upToDateWhen {false}його testLogging { [...] }. Продовжуйте читати тут .

Мир.


11
Гей, просто хотів повідомити, що я знайшов спосіб не говорити gradle cleanTest testкожного разу (станом на Gradle 1,12). Додайте outputs.upToDateWhen {false}до, testLogging {...}і це повинно зробити трюк. Це змусить Gradle кожного разу запускати тести. Я знайшов це на форумах Gradle, розміщених самим Доктером . Сподіваюсь, це допомагає.
sparc_spread

Я б включив, exceptionFormat "full"щоб отримати детальну інформацію про те, що не вдалося, корисно, коли ви використовуєте AssertJ або подібну лібу.
Шайрон Толедо

5
Замість цього cleanTestви можете використовуватиtest --rerun-tasks
gavenkoa

2
@gavenkoa Я думаю --rerun-tasks, що змусить усі ваші завдання повторитись, а не лише завдання для тестів.
ThomasW

2
насправді, cleanTest testостання Android Studio і gradle 3.3 не працює на моєму боці, але --rerun-tasksзробив трюк. Не знаю чому. Але прочитавши цю відповідь, справді вирішив мій головний біль, де проводиться тестовий журнал f ** king після того, як я додаю кожну річ.
Wingzero

111

Відмова від відповідальності: Я розробник плагіну Testle Logger Gradle.

Ви можете просто використати плагін 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

@ dk7 за замовчуванням лише тести, що тривають більше 1 секунди, друкують тривалість. Докладнішу інформацію див. У документації . Якщо ви хочете побачити все тривалості, просто встановіть slowThresholdв 0.
adarshr

1
@ HaroldL.Brown Так, справді :) Я просто трохи заграв декількома речами в даний час, але це дуже сильно живе.
adarshr

1
Yup @VadymTyemirov. Те саме, що github.com/radarsh/gradle-test-logger-plugin/isissue/137, коли я документую 🙂
adarshr

49

Додайте це, щоб build.gradleзапобігти ковтанню студла та стридера.

test {
    testLogging.showStandardStreams = true
}

Це задокументовано тут .


38

Завдання 'test' не працює для плагіна Android, а для плагіна Android використовуйте наступне:

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

Дивіться наступне: https://stackoverflow.com/a/31665341/3521637


3
Дивовижно. FYI Майбутнє мене - збережіть свої дві хвилини, не поміщаючи його всередину блоку Android {}
Shubham Chaudhary

18

Як підсумок чудової відповіді Шубхема, я хочу запропонувати використовувати значення enum замість рядків . Перегляньте документацію класу 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

У Gradle, використовуючи плагін Android:

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

Тоді вихід буде:

Виконання тестового тестуConversionMinutes [org.example.app.test.DurationTest] з результатом: SUCCESS


3

Злиття чудової відповіді Шубхема і JJD використовують enum замість рядка

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

Виходячи з відповіді Бенджаміна Мушка (19 березня 2011 р.), Ви можете використовувати -iпрапор разом із грепом , щоб відфільтрувати 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передається в другу команду grep, яка відфільтрує багато небажаних рядків на основі регулярного виразу. "-E"вмикає режим регулярного вираження і "|"означає "або". Ім'я та результат одиниці тесту дозволяється відображати за допомогою " > ", а загальний статус дозволено за допомогою "BUILD". У м'якому фільтрі "-v"прапор означає "не містить" і "^"означає "початок рядка". Таким чином, він викреслює всі рядки, які починаються з "Виконання" або починаються зі "Створення" тощо.


Приклад тестування блоку вимірювальних приладів Android, з ступенем 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:"

Приклад покриття тесту на одиницю Якоко, з ступеням 4.10:

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

0

Якщо у вас є build.gradle.ktsнаписаний на 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)")
        }
    }))
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.