Spock testing output from printing function
Asked Answered
A

1

5

I just wanted to know how I can test the output from a groovy function that does a println of some stuff. So the stupid class I wrote is:

class FriendlyGreeterLib {
    def greet(name) {
        println "${name.capitalize()}"
    }
}

The corresponding test would work, if greet() returned a string. But how to check the output of println to stdout...

import spock.lang.Shared
import spock.lang.Specification

class FriendlyGreeterLibTest extends Specification{

    @Shared lib

    def setupSpec() {
        lib = new FriendlyGreeterLib()
    }

    def "FriendlyGreeterLib greets capitalized"() {
        expect:
        lib.greet(x) == y

        where:
        x | y
        'fred' | 'Fred'
        'FRED' | 'FRED'
        'fRED' | 'FRED'
    }
}
Ace answered 20/11, 2017 at 15:51 Comment(2)
What is the purpose of testing it? It will work.. If you need to test the input, move the logic responsible for message formatting to a separate class.Amulet
Print the output to a file, then check file content.Mattheus
A
8

Thanks to Royg, I came to the idea just to set a different stream for System.out and read out the streams buffer. I'm not sure if this is absolutely elegant, but it works:

Complete Test:

import spock.lang.Shared
import spock.lang.Specification

class FriendlyGreeterLibTest extends Specification{

    @Shared lib

    def setupSpec() {
        lib = new FriendlyGreeterLib()
    }

    def "FriendlyGreeterLib greets capitalized"() {
        when:
        def buffer = new ByteArrayOutputStream()
        System.out = new PrintStream(buffer)

        and:
        lib.greet(x)

        then:
        buffer.toString() == y

        where:
        x | y
        'fred' | 'Fred'
        'FRED' | 'FRED'
        'fRED' | 'FRED'
    }
}
Ace answered 21/11, 2017 at 9:30 Comment(2)
Nice... prior to this I was using org.junit.contrib.java.lang.system.SystemOutRule ... which works... but is needlessly complicated. Disagree with Opal's implication that checking stdout output is nothing to do with testing. Arguably it may be nothing to do with UNIT testing. But not all testing is unit testing.Latinism
I think what @Amulet thinks is about abstracting the string manipulating away from the pure output, which can be any kind of stream, file or whatnot. In the end, testing the contents of the output on a terminal is some kind of "frontend" testing... ;-)Ace

© 2022 - 2024 — McMap. All rights reserved.