Gradle: Jak wyświetlać wyniki testu w konsoli w czasie rzeczywistym?


231

Chciałbym zobaczyć wyniki testu (system.out / err, rejestruj komunikaty z testowanych komponentów), ponieważ działają one w tej samej konsoli, którą uruchamiam:

gradle test

I nie czekaj, aż testy zostaną wykonane, aby przejrzeć raporty z testów (które są generowane tylko po zakończeniu testów, więc nie mogę „ogonić” niczego podczas testów)

Odpowiedzi:


169

Możesz uruchomić Gradle z poziomem rejestrowania INFO w wierszu poleceń. Pokaże wynik każdego testu podczas jego działania. Minusem jest to, że uzyskasz znacznie więcej wyników w przypadku innych zadań.

gradle test -i

13
Z wersją 1.0-kamień milowy 6 Gradle DSL pozwala teraz skonfigurować to bezpośrednio przy użyciu testLogging.showStandardStreams = true w testzamknięciu.
Benjamin Muschko

4
To nie działa w klasie 1.11. Otrzymuję dużo wyników debugowania, ale nie wyniki poszczególnych testów.
David Moles

44
To -irzuci kilka nieistotnych informacji na terminal.
Thuy Trinh,

9
Oprócz wielu bezużytecznych danych wyjściowych nic nie jest wyświetlane dla testów, które przejdą pomyślnie i nie wygenerują danych wyjściowych.
toolbear

1
Możesz użyć grepdo odfiltrowania tysięcy niechcianych linii. Zobacz stackoverflow.com/questions/3963708/...
Mr-IDE,

172

Oto moja wymyślna wersja:

fantazyjny wynik testu

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
Moim zdaniem jest to najlepsza odpowiedź tutaj. Zawiera największy zestaw opcji i każdy może skonfigurować swoje testy według swoich potrzeb.
Slav

2
@sealskej gdzie muszę skopiować ten kod i jak go uruchomić z wiersza poleceń? EDYCJA: rozumiem - po prostu dodaj go do gradle.config modułów i uruchom normalnie
hardysim

Miły! Właśnie usunąłem potoki |z, startItemponieważ uruchamianie zadania przez Android Studio 2.2.3 rozpoznało je jako błędy w komunikatach i było denerwujące w przypadku kompilacji powodzenia.
madlymad

1
Jak włączyłeś kolory?
Durga Swaroop

1
@DurgaSwaroop Działa dla mnie od razu po wyjęciu z pudełka. Upewnij się, że twoja aplikacja terminalowa obsługuje kolory. Osobiście korzystam z aplikacji iTerm2.
Shubham Chaudhary

156

Możesz dodać Groovy zamknięcie w pliku build.gradle, który rejestruje się za Ciebie:

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

Na konsoli wyświetla się następująco:

: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

Od wersji 1.1 Gradle obsługuje znacznie więcej opcji rejestrowania wyników testu . Dzięki tym dostępnym opcjom możesz osiągnąć podobny wynik w następującej konfiguracji:

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

4
wygeneruje to wynik dopiero po wykonaniu testu. to, czego szukam, to zobaczyć rejestrowanie / raportowanie / system out / printlns itp. podczas testów . pomyśl o wykonywaniu testów za pomocą maven lub tylko w IntelliJ / Eclipse: dane wyjściowe są wytwarzane w czasie rzeczywistym.
Tolitius

Okej, przepraszam za niezrozumienie twojego pytania. W takim przypadku powinieneś zapoznać się z następującą częścią dokumentacji Gradle: gradle.org/logging.html#sec:external_tools
stefanglase

1
Jaką faktycznie wprowadzam zmianę, aby zobaczyć wynik? Widzę te wszystkie niestandardowe obiekty nasłuchiwania i inne rzeczy w dokumentacji, ale nie mam pojęcia, jak to skonfigurować.
jpswain

118

Jak odpowiedział stefanglase :

dodanie następującego kodu do build.gradle(od wersji 1.1) działa dobrze dla danych wyjściowych z pozytywnych , pomijanych i nieudanych testów.

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

Chciałbym dodatkowo powiedzieć (dowiedziałem się, że jest to problem na początek), że gradle testpolecenie wykonuje test tylko raz na zmianę .

Więc jeśli uruchomisz go po raz drugi, wyniki testu nie będą wyświetlane . Można również zobaczyć w produkcji budowlanej: Gradle czym mówi się na bieżąco na testach. Więc nie jest wykonywany n-ty raz.

Inteligentna klasa!

Jeśli chcesz wymusić uruchomienie przypadków testowych, użyj gradle cleanTest test.

To nieco nie na temat, ale mam nadzieję, że pomoże niektórym początkującym.

edytować

Jak sparc_spread stwierdził w komentarzach:

Jeśli chcesz wymusić na gradie, aby zawsze uruchamiał nowe testy (co może nie zawsze być dobrym pomysłem), możesz outputs.upToDateWhen {false}do niego dodać testLogging { [...] }. Kontynuuj czytanie tutaj .

Pokój.


11
Hej, chciałem tylko poinformować, że znalazłem sposób, by nie musieć za gradle cleanTest testkażdym razem mówić (od wersji 1.12). Dodaj outputs.upToDateWhen {false}do testLogging {...}i że powinno załatwić sprawę. Zmusi to Gradle do uruchomienia testów za każdym razem. Znalazłem to na forach Gradle, opublikowanych przez samego Docktera . Mam nadzieję że to pomoże.
sparc_spread

Chciałbym to exceptionFormat "full", aby uzyskać szczegółowe informacje na temat tego, co nie udało, przydatna, gdy używasz AssertJ lub podobnego lib.
Shairon Toledo

5
Zamiast cleanTestciebie możesz użyćtest --rerun-tasks
gavenkoa

2
@gavenkoa Myślę, że --rerun-taskssprawi, że wszystkie twoje zadania zostaną uruchomione ponownie, nie tylko zadania do testów.
ThomasW

2
w rzeczywistości cleanTest testw najnowszym Android Studio i klasie 3.3 nie działa po mojej stronie, ale załatwiło sprawę --rerun-tasks. Nie wiem dlaczego. Ale przeczytanie tej odpowiedzi naprawdę rozwiązało mój ból głowy, gdzie do cholery loguje się test po dodaniu wszystkiego.
Wingzero,

111

Oświadczenie: Jestem twórcą wtyczki Gradle Test Logger.

Możesz po prostu użyć wtyczki Gradle Test Logger, aby wydrukować piękne logi na konsoli. Wtyczka używa rozsądnych ustawień domyślnych, aby zadowolić większość użytkowników z niewielką konfiguracją lub bez niej, ale oferuje także szereg motywów i opcji konfiguracji, które zadowolą każdego.

Przykłady

Standardowy motyw Standardowy motyw

Motyw Mocha Motyw mokka

Stosowanie

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

Upewnij się, że zawsze otrzymujesz najnowszą wersję od Gradle Central .

Konfiguracja

W ogóle nie potrzebujesz żadnej konfiguracji. Jednak wtyczka oferuje kilka opcji. Można to zrobić w następujący sposób (pokazane wartości domyślne):

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
}

Mam nadzieję, że spodoba ci się korzystanie z niego.


3
Miły! Doprowadziło to do zadziwiającego czegoś tak prostego, jak podsumowanie pozytywnych / nieudanych / pominiętych testów.
MarkHu

Właśnie zintegrowałem wtyczkę, ale nie widzę czasu trwania testów, tak jak w twoim git dla każdego testu w nawiasie (1.6s) Jak to włączyć?
dk7,

@ dk7 domyślnie drukowane są tylko testy trwające dłużej niż 1 sekundę. Więcej informacji znajduje się w dokumentacji . Jeśli chcesz zobaczyć wszystkie czasy trwania, po prostu ustaw slowThresholdna 0.
adarshr

1
@ HaroldL.Brown Tak, rzeczywiście :) Jestem trochę zalany przez kilka rzeczy, ale jest bardzo żywy.
adarshr

1
Tak @VadymTyemirov. To samo co github.com/radarsh/gradle-test-logger-plugin/issues/137 po udokumentowaniu 🙂
adarshr

49

Dodaj to, aby build.gradlezatrzymać gradle od połykania stdout i stderr.

test {
    testLogging.showStandardStreams = true
}

Jest to udokumentowane tutaj .



18

Jako kontynuacja wspaniałej odpowiedzi Shubhama chciałbym zasugerować użycie wartości wyliczeniowych zamiast łańcuchów . Proszę spojrzeć na dokumentację klasy 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

Moja ulubiona minimalistyczna wersja oparta na odpowiedzi Shubhama Chaudhary'ego. wprowadź opis zdjęcia tutaj

Umieść to w build.gradlepliku:

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

7

W Gradle przy użyciu wtyczki do Androida:

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

Następnie dane wyjściowe będą:

Wykonywanie testu testConversionMinutes [org.example.app.test.DurationTest] z wynikiem: SUCCESS


3

Połączenie doskonałej odpowiedzi Shubhama i JJD używają wyliczenia zamiast łańcucha

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
Proszę o dodanie dodatkowego kontekstu wokół odpowiedzi. Odpowiedzi zawierające tylko kod lub tylko łącze są trudne do zrozumienia. Pomoże zarówno pytającemu, jak i przyszłym czytelnikom, czy możesz dodać więcej informacji w swoim poście.
RBT

2

Kontynuując odpowiedź Benjamina Muschko (19 marca 2011 r.), Możesz użyć -iflagi wraz z grep , aby odfiltrować tysiące niechcianych linii. Przykłady:

Silny filtr - wyświetla tylko nazwę i wynik testu każdej jednostki oraz ogólny status kompilacji. Błędy konfiguracji lub wyjątki nie są wyświetlane.

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

Filtr miękki - wyświetla nazwę i wynik testu każdej jednostki, a także błędy konfiguracji / wyjątki. Ale będzie również zawierać pewne nieistotne informacje:

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

Filtr miękki, Alternatywna składnia: (tokeny wyszukiwania są podzielone na poszczególne ciągi)

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

Wyjaśnienie, jak to działa: Dane wyjściowe pierwszego polecenia, ./gradlew test -isą przesyłane potokowo do drugiego polecenia grep, które odfiltruje wiele niechcianych wierszy na podstawie wyrażenia regularnego. "-E"włącza tryb wyrażeń regularnych i "|"oznacza „lub”. Nazwa testu jednostkowego i wynik mogą być wyświetlane za pomocą " > ", a ogólny status jest dozwolony za pomocą "BUILD". W filtrze miękkim "-v"flaga oznacza „nie zawiera” i "^"oznacza „początek linii”. Usuwa więc wszystkie wiersze, które zaczynają się od „Wykonanie” lub zaczynają się od „Tworzenie” itp.


Przykład testów jednostkowych przyrządów z systemem Android, z klasą 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:"

Przykład pokrycia testowego jednostki Jacoco z klasą 4.10:

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

0

Jeśli masz build.gradle.ktsnapisane w DSL Kotlin , możesz wydrukować wyniki testu (opracowałem projekt wieloplatformowy Kotlin , bez wtyczki „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)")
        }
    }))
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.