Gradle: Como exibir os resultados dos testes no console em tempo real?

231

Gostaria de ver os resultados dos testes (system.out / err, mensagens de log dos componentes que estão sendo testados) enquanto eles são executados no mesmo console que eu executo:

gradle test

E não espere até que os testes sejam concluídos para examinar os relatórios de teste (que são gerados somente quando os testes são concluídos, portanto, não posso "f-tail" de nada enquanto os testes estão em execução)

tolício
fonte

Respostas:

169

Você pode executar o Gradle com o nível de log INFO na linha de comando. Ele mostra o resultado de cada teste enquanto eles estão em execução. A desvantagem é que você obterá muito mais saída para outras tarefas também.

gradle test -i
Benjamin Muschko
fonte
13
Com a etapa 1.0 1.0, o Gradle DSL agora permite configurar isso diretamente usando testLogging.showStandardStreams = true dentro do testfechamento.
22711 Benjamin Muschko
4
Isso não funciona no gradle 1.11. Recebo muita saída de depuração, mas não os resultados individuais dos testes.
David Moles
44
Isso -ilançará um monte de informações irrelevantes no terminal.
precisa
9
Além de muita saída inútil, nada é exibido para testes que passam e não geram saída.
Toolbear
1
Você pode usar greppara filtrar milhares de linhas indesejadas. Veja stackoverflow.com/questions/3963708/…
Mr-IDE
172

Aqui está a minha versão chique:

resultado de teste extravagante

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
fonte
13
Na minha opinião, esta é a melhor resposta aqui. Ele contém o maior conjunto de opções e todos podem configurar seus testes conforme necessário.
Slav
2
@sealskej onde eu preciso copiar esse código e como executá-lo na linha de comando? EDIT: got-lo - basta adicioná-lo à gradle.config das módulos e funcionar normalmente
hardysim
Agradável! Acabei de remover os canos| do startItemporque a execução da tarefa via Android Studio 2.2.3 os reconhece como erros nas mensagens e era irritante nas compilações de sucesso.
madlymad
1
E como você habilitou as cores?
Durga Swaroop
1
@DurgaSwaroop Funciona imediatamente para mim. Verifique se o aplicativo do seu terminal suporta cores. Eu pessoalmente uso o aplicativo iTerm2.
Shubham Chaudhary
156

Você pode adicionar um fechamento Groovy dentro do arquivo build.gradle que faz o log para você:

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

No seu console, ele fica assim:

: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

Desde a versão 1.1 Gradle suporta muito mais opções para registrar a saída do teste . Com essas opções em mãos, você pode obter uma saída semelhante com a seguinte configuração:

test {
    testLogging {
        events "passed", "skipped", "failed"
    }
}
stefanglase
fonte
4
isso só produzirá a saída após a execução do teste. o que estou procurando é ver os registros / relatórios / saídas do sistema / printlns etc. como testes em execução . pense em executar testes com o maven ou apenas no IntelliJ / Eclipse: a saída é produzida em tempo real.
tolitius 28/11
Ok, desculpe por não ter entendido sua pergunta. Nesse caso, você deve dar uma olhada na seguinte parte da documentação da Gradle: gradle.org/logging.html#sec:external_tools
stefanglase
1
Então, que mudança eu realmente faço para ver a saída? Vejo todos esses ouvintes personalizados e outras coisas na documentação, mas não tenho idéia de como configurar isso.
Jspwain
118

Como stefanglase respondeu:

adicionar o código a seguir ao build.gradle(desde a versão 1.1) funciona bem para saída em testes aprovados , ignorados e com falha .

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

O que quero dizer adicionalmente (descobri que isso é um problema para iniciantes) é que o gradle testcomando executa o teste apenas uma vez por alteração .

Então, se você estiver executando o segunda vez, não haverá saída nos resultados do teste . Você também pode ver isso na saída do edifício: gradle diz UP-TO-DATE nos testes. Portanto, não é executado pela n-ésima vez.

Gradle inteligente!

Se você deseja forçar a execução dos casos de teste, use gradle cleanTest test .

Este tópico está um pouco fora do tópico, mas espero que ajude alguns novatos.

editar

Como sparc_spread afirmou nos comentários:

Se você deseja forçar o gradle a executar sempre novos testes (o que nem sempre é uma boa idéia), você pode adicionar outputs.upToDateWhen {false}a testLogging { [...] }. Continue lendo aqui .

Paz.

Langusten Gustel
fonte
11
Ei, só queria que você soubesse que encontrei uma maneira de não dizer a gradle cleanTest testcada vez (a partir do Gradle 1.12). Adicionar outputs.upToDateWhen {false}para testLogging {...}e que deve fazer o truque. Isso forçará o Gradle a executar os testes todas as vezes. Encontrei isso nos fóruns de Gradle, postados pelo próprio Dockter . Espero que isto ajude.
Sparc_spread 15/05
Eu incluiria exceptionFormat "full"para obter detalhes sobre o que falhou, útil quando você estiver usando o AssertJ ou uma biblioteca semelhante.
Shairon Toledo 27/11/2015
5
Em vez de cleanTestvocê pode usartest --rerun-tasks
gavenkoa
2
@gavenkoa Acho --rerun-tasksque todas as suas tarefas serão executadas novamente, não apenas as tarefas dos testes.
ThomasW
2
na verdade, cleanTest testno Android Studio e no gradle 3.3 mais recentes não está funcionando do meu lado, mas --rerun-tasksfez o truque. Não sei porque. Mas ler esta resposta realmente resolveu minha dor de cabeça, onde está o registro do teste do f ** king depois que eu adiciono tudo.
Wingzero 13/06
111

Isenção de responsabilidade: Eu sou o desenvolvedor do Gradle Test Logger Plugin.

Você pode simplesmente usar o Gradle Test Logger Plugin para imprimir belos logs no console. O plug-in usa padrões sensatos para satisfazer a maioria dos usuários com pouca ou nenhuma configuração, mas também oferece vários temas e opções de configuração para todos os gostos.

Exemplos

Tema padrão Tema padrão

Tema Mocha Tema Mocha

Uso

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

Certifique-se de sempre obter a versão mais recente do Gradle Central .

Configuração

Você não precisa de nenhuma configuração. No entanto, o plugin oferece algumas opções. Isso pode ser feito da seguinte maneira (valores padrão mostrados):

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
}

Espero que você goste de usá-lo.

adarshr
fonte
3
Agradável! Surpreendente algo tão simples quanto um resumo dos testes aprovados / reprovados / ignorados levou a isso.
MarkHu
Acabei de integrar o plug-in, mas não estou vendo a duração dos testes, como no seu git para todos os testes entre parênteses (1.6s). Como habilitar isso?
dk7
@ dk7 por padrão, apenas os testes que levam mais de 1 segundo para serem executados terão a duração impressa. Veja a documentação para mais informações. Se você quiser ver todas as durações, basta definir slowThresholdcomo 0.
adarshr
1
@ HaroldL.Brown Sim, de fato :) Estou um pouco inundado com algumas coisas atualmente, mas está muito vivo.
adarshr 6/04
1
Yup @VadymTyemirov. O mesmo que github.com/radarsh/gradle-test-logger-plugin/issues/137, uma vez que eu o documento 🙂
adarshr
49

Adicione isto para build.gradleimpedir que o gradle engula stdout e stderr.

test {
    testLogging.showStandardStreams = true
}

Está documentado aqui .

Darwin
fonte
38

A tarefa 'test' não funciona para o plug-in Android; para o plug-in Android, use o seguinte:

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

Veja o seguinte: https://stackoverflow.com/a/31665341/3521637

user3521637
fonte
3
Impressionante. FYI Future me - economize seus dois minutos, não colocando-o dentro do bloco Android {} #
Shubham Chaudhary 10/11
18

Como acompanhamento da grande resposta de Shubham, eu gostaria de sugerir o uso de valores enum em vez de strings . Por favor, dê uma olhada na documentação da 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
fonte
12

Minha versão minimalista favorita baseada na resposta Shubham Chaudhary. insira a descrição da imagem aqui

Coloque isso no build.gradlearquivo:

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

Em Gradle usando o plug-in Android:

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

Então a saída será:

Executando o teste testConversionMinutes [org.example.app.test.DurationTest] com o resultado: SUCCESS

radeklos
fonte
3

A mescla da grande resposta de Shubham e o JJD usam enum em vez de 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))
           }
       }
   }
}
odemolliens
fonte
2
Peço que você adicione um pouco mais de contexto à sua resposta. As respostas somente de código ou somente de link são difíceis de entender. Isso ajudará os solicitantes e os futuros leitores, se você puder adicionar mais informações em sua postagem.
RBT
2

Seguindo a resposta de Benjamin Muschko (19 de março de 2011), você pode usar a -ibandeira junto com o grep , para filtrar milhares de linhas indesejadas. Exemplos:

Filtro forte - Exiba apenas o nome e o resultado de cada teste de unidade e o status geral da compilação. Erros ou exceções de instalação não são exibidos.

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

Filtro suave - Exiba o nome e o resultado de cada teste de unidade, bem como os erros / exceções de configuração. Mas também incluirá algumas informações irrelevantes:

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

Filtro suave, sintaxe alternativa: (os tokens de pesquisa são divididos em sequências individuais)

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

Explicação de como funciona: A saída do primeiro comando ./gradlew test -i,, é canalizada para um segundo comando grep, que filtrará muitas linhas indesejadas com base em uma expressão regular. "-E"ativa o modo de expressão regular e "|"significa "ou". É permitido exibir um nome e um resultado do teste de unidade usando " > ", e o status geral é permitido com "BUILD". No filtro flexível, o "-v"sinalizador significa "não contém" e "^"significa "início da linha". Portanto, remove todas as linhas que começam com "Executando" ou com "Criando" etc.


Exemplo para testes de unidade de instrumentação Android, com 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:"

Exemplo de cobertura de teste de unidade Jacoco, com 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
fonte
0

Se você possui um DSLbuild.gradle.kts escrito no Kotlin, pode imprimir os resultados dos testes (eu estava desenvolvendo um projeto de plataforma múltipla do kotlin, sem o plugin "java" aplicado):

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
fonte
0

Basta adicionar o seguinte fechamento ao seu build.gradle. a saída será impressa após a execução de cada teste.

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