Gradle: Comment afficher les résultats des tests dans la console en temps réel?

231

Je voudrais voir les résultats des tests (system.out / err, journaux des composants testés) lorsqu'ils s'exécutent dans la même console que j'exécute:

gradle test

Et n'attendez pas que les tests soient terminés pour consulter les rapports de test (qui ne sont générés que lorsque les tests sont terminés, donc je ne peux rien "tail -f" pendant que les tests sont en cours)

tolitius
la source

Réponses:

169

Vous pouvez exécuter Gradle avec le niveau de journalisation INFO sur la ligne de commande. Il vous montrera le résultat de chaque test pendant leur exécution. L'inconvénient est que vous obtiendrez également beaucoup plus de sortie pour d'autres tâches.

gradle test -i
Benjamin Muschko
la source
13
Avec 1.0-milestone 6, le Gradle DSL vous permet maintenant de le configurer directement en utilisant testLogging.showStandardStreams = true dans la testfermeture.
Benjamin Muschko
4
Cela ne fonctionne pas dans le grade 1.11. J'obtiens beaucoup de sortie de débogage, mais pas les résultats des tests individuels.
David Moles
44
Cela -ijettera un tas d'informations non pertinentes sur le terminal.
Thuy Trinh
9
En plus de nombreuses sorties inutiles, rien ne s'affiche pour les tests qui réussissent et ne génèrent aucune sortie.
Toolbear
1
Vous pouvez utiliser greppour filtrer les milliers de lignes indésirables. Voir stackoverflow.com/questions/3963708/…
Mr-IDE
172

Voici ma version fantaisie:

résultat du test de fantaisie

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 Chaudhary
la source
13
À mon avis, c'est la meilleure réponse ici. Il contient le plus grand ensemble d'options et chacun peut configurer ses tests selon ses besoins.
Slav
2
@sealskej où dois-je copier ce code et comment l'exécuter à partir de la ligne de commande? EDIT: compris - ajoutez-le simplement au module gradle.config des modules et exécutez-le normalement
hardysim
Agréable! Je viens de supprimer les tuyaux |du startItemcar l'exécution de la tâche via Android Studio 2.2.3 les reconnaît comme des erreurs dans les messages et c'était ennuyeux pour les builds réussis.
madlymad
1
Et comment avez-vous activé les couleurs?
Durga Swaroop
1
@DurgaSwaroop Fonctionne hors de la boîte pour moi. Veuillez vous assurer que votre application de terminal prend en charge les couleurs. J'utilise personnellement l'application iTerm2.
Shubham Chaudhary
156

Vous pouvez ajouter une fermeture Groovy dans votre fichier build.gradle qui effectue la journalisation pour vous:

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

Sur votre console, il se lit alors comme suit:

: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

Depuis la version 1.1, Gradle prend en charge beaucoup plus d'options pour enregistrer la sortie de test . Avec ces options à portée de main, vous pouvez obtenir une sortie similaire avec la configuration suivante:

test {
    testLogging {
        events "passed", "skipped", "failed"
    }
}
stefanglase
la source
4
cela ne produira la sortie qu'après l' exécution du test. ce que je recherche, c'est de voir la journalisation / rapport / sorties système / printlns etc. pendant que les tests sont en cours . pensez à exécuter des tests avec maven ou simplement dans IntelliJ / Eclipse: la sortie est produite en temps réel.
tolitius
D'accord, désolé d'avoir mal compris votre question. Pour ce cas, vous devriez jeter un œil à la partie suivante de la documentation Gradle: gradle.org/logging.html#sec:external_tools
stefanglase
1
Alors, quel changement dois-je réellement faire pour voir la sortie? Je vois tous ces écouteurs personnalisés et tout ça dans la documentation, mais je ne sais pas comment configurer cela.
jpswain
118

Comme l'a répondu stefanglase :

l'ajout du code suivant à votre build.gradle(depuis la version 1.1) fonctionne bien pour la sortie des tests réussis , ignorés et échoués .

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

Ce que je veux dire en plus (j'ai découvert que c'est un problème pour les démarreurs), c'est que la gradle testcommande n'exécute le test qu'une seule fois par changement .

Donc, si vous l'exécutez la deuxième fois, il n'y aura pas de sortie sur les résultats des tests . Vous pouvez également le voir dans la sortie du bâtiment: gradle indique ensuite UP-TO-DATE lors des tests. Donc, ce n'est pas exécuté une énième fois.

Gradle intelligent!

Si vous souhaitez forcer l'exécution des scénarios de test, utilisez gradle cleanTest test.

Ceci est légèrement hors sujet mais j'espère que cela aidera certains débutants.

Éditer

Comme l'a indiqué sparc_spread dans les commentaires:

Si vous voulez forcer gradle à de nouveaux essais toujours courir ( ce qui pourrait être pas toujours une bonne idée) que vous pouvez ajouter outputs.upToDateWhen {false}à testLogging { [...] }. Continuez à lire ici .

Paix.

Langusten Gustel
la source
11
Hé, je voulais juste vous faire savoir que j'ai trouvé un moyen de ne pas avoir à dire à gradle cleanTest testchaque fois (à partir de Gradle 1.12). Ajoutez outputs.upToDateWhen {false}à testLogging {...}et cela devrait faire l'affaire. Cela obligera Gradle à exécuter les tests à chaque fois. Je l'ai trouvé dans les forums Gradle, publiés par Dockter lui-même . J'espère que cela t'aides.
sparc_spread
J'inclus exceptionFormat "full"pour obtenir des détails sur ce qui a échoué, utile lorsque vous utilisez AssertJ ou lib similaire.
Shairon Toledo
5
Au lieu de cleanTestvous pouvez utilisertest --rerun-tasks
gavenkoa
2
@gavenkoa Je pense --rerun-tasksque toutes vos tâches seront réexécutées, pas seulement les tâches pour les tests.
ThomasW
2
en fait, cleanTest testsur le dernier Android Studio et Gradle 3.3 ne fonctionne pas de mon côté, mais a --rerun-tasksfait l'affaire. Je ne sais pas pourquoi. Mais la lecture de cette réponse a vraiment résolu mon mal de tête, où est la journalisation du test f ** king après avoir ajouté tout.
Wingzero
111

Avertissement: je suis le développeur du plug-in Gradle Test Logger.

Vous pouvez simplement utiliser le plug-in Gradle Test Logger pour imprimer de beaux journaux sur la console. Le plugin utilise des valeurs par défaut raisonnables pour satisfaire la plupart des utilisateurs avec peu ou pas de configuration, mais offre également un certain nombre de thèmes et d'options de configuration pour convenir à tout le monde.

Exemples

Thème standard Thème standard

Thème Mocha Thème moka

Usage

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

Assurez-vous de toujours obtenir la dernière version de Gradle Central .

Configuration

Vous n'avez besoin d'aucune configuration. Cependant, le plugin propose quelques options. Cela peut être fait comme suit (valeurs par défaut affichées):

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
}

J'espère que vous apprécierez de l'utiliser.

adarshr
la source
3
Agréable! Une chose étonnante aussi simple qu'un résumé des tests réussis / échoués / sautés y a conduit.
MarkHu
Je viens d'intégrer le plugin, mais je ne vois pas la durée des tests, comme dans votre git pour chaque test entre parenthèses (1.6s) Comment activer cela?
dk7
@ dk7 par défaut, seuls les tests dont l'exécution prend plus d'une seconde auront la durée imprimée. Voir la documentation pour plus d'informations. Si vous souhaitez voir toutes les durées, définissez simplement slowThresholdsur 0.
adarshr
1
@ HaroldL.Brown Oui en effet :) Je suis juste un peu submergé par quelques choses actuellement, mais c'est très vivant.
adarshr
1
Yup @VadymTyemirov. Identique à github.com/radarsh/gradle-test-logger-plugin/issues/137 une fois que je l'ai documenté 🙂
adarshr
49

Ajoutez ceci pour build.gradleempêcher Gradle d'avaler stdout et stderr.

test {
    testLogging.showStandardStreams = true
}

C'est documenté ici .

Darwin
la source
38

La tâche 'test' ne fonctionne pas pour le plugin Android, pour le plugin Android, utilisez ce qui suit:

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

Voir ce qui suit: https://stackoverflow.com/a/31665341/3521637

user3521637
la source
3
Impressionnant. FYI Future me - économisez vos deux minutes en ne le plaçant pas dans le bloc android {}
Shubham Chaudhary
18

Dans le prolongement de la grande réponse de Shubham, j'aime suggérer d'utiliser des valeurs d' énumération au lieu de chaînes . Veuillez consulter la documentation de la classe 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
    }
}
JJD
la source
12

Ma version minimaliste préférée basée sur la réponse de Shubham Chaudhary. entrez la description de l'image ici

Mettez ceci dans un build.gradlefichier:

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

Dans Gradle en utilisant le plugin Android:

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

La sortie sera alors:

Exécution du test testConversionMinutes [org.example.app.test.DurationTest] avec le résultat: SUCCESS

radeklos
la source
3

Fusion de la grande réponse de Shubham et JJD utilise une énumération au lieu d'une chaîne

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))
           }
       }
   }
}
odemolliens
la source
2
Je vous demande de bien vouloir ajouter un peu plus de contexte autour de votre réponse. Les réponses de code uniquement ou de lien uniquement sont difficiles à comprendre. Cela aidera le demandeur et les futurs lecteurs à la fois si vous pouvez ajouter plus d'informations dans votre message.
RBT
2

Suite à la réponse de Benjamin Muschko (19 mars 2011), vous pouvez utiliser le -idrapeau avec grep pour filtrer des milliers de lignes indésirables. Exemples:

Filtre puissant - N'affiche que le nom et le résultat de chaque test unitaire, ainsi que l'état général de la construction. Les erreurs ou exceptions de configuration ne s'affichent pas.

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

Filtre souple - Affiche le nom et le résultat de chaque test unitaire, ainsi que les erreurs / exceptions de configuration. Mais il comprendra également des informations non pertinentes:

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

Filtre souple, syntaxe alternative: (les jetons de recherche sont divisés en chaînes individuelles)

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

Explication de son fonctionnement: la sortie de la première commande ./gradlew test -i,, est dirigée vers une deuxième commande grep, qui filtrera de nombreuses lignes indésirables sur la base d'une expression régulière. "-E"active le mode d'expression régulière et "|"signifie "ou". Un nom et un résultat de test unitaire peuvent s'afficher à l'aide de" > " , et l'état général est autorisé avec "BUILD". Dans le filtre souple, le "-v"drapeau signifie "ne contenant pas" et "^"signifie "début de ligne". Il supprime donc toutes les lignes commençant par "Exécuter" ou commencer par "Créer", etc.


Exemple pour les tests unitaires d'instrumentation Android, avec 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:"

Exemple de couverture de test unitaire Jacoco, avec gradle 4.10:

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

Si vous avez un DSLbuild.gradle.kts écrit dans Kotlin, vous pouvez imprimer les résultats des tests avec (je développais un projet multi-plateforme kotlin, sans plugin "java" appliqué):

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)")
        }
    }))
}
Enrico
la source
0

Ajoutez simplement la fermeture suivante à votre build.gradle. la sortie sera imprimée après l'exécution de chaque test.

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