I have a simple function I want to test:
func (t *Thing) print(min_verbosity int, message string) { if t.verbosity >= minv { fmt.Print(message) } }
But how can I test what the function actually sends to standard output? Test::Output does what I want in Perl. I know I could write all my own boilerplate to do the same in Go (as described here):
orig = os.Stdout r,w,_ = os.Pipe() thing.print("Some message") var buf bytes.Buffer io.Copy(&buf, r) w.Close() os.Stdout = orig if(buf.String() != "Some message") { t.Error("Failure!") }
But that's a lot of extra work for every single test. I'm hoping there's a more standard way, or perhaps an abstraction library to handle this.
One thing to also remember, there's nothing stopping you from writing functions to avoid the boilerplate.
For example I have a command line app that uses log
and I wrote this function:
func captureOutput(f func()) string { var buf bytes.Buffer log.SetOutput(&buf) f() log.SetOutput(os.Stderr) return buf.String() }
Then used it like this:
output := captureOutput(func() { client.RemoveCertificate("www.example.com") }) assert.Equal(t, "removed certificate www.example.com\n", output)
Using this assert library: http://godoc.org/github.com/stretchr/testify/assert.
You can do one of three things. The first is to use Examples.
The package also runs and verifies example code. Example functions may include a concluding line comment that begins with "Output:" and is compared with the standard output of the function when the tests are run. (The comparison ignores leading and trailing space.) These are examples of an example:
func ExampleHello() { fmt.Println("hello") // Output: hello }
The second (and more appropriate, IMO) is to use fake functions for your IO. In your code you do:
var myPrint = fmt.Print func (t *Thing) print(min_verbosity int, message string) { if t.verbosity >= minv { myPrint(message) // N.B. } }
And in your tests:
func init() { myPrint = fakePrint // fakePrint records everything it's supposed to print. } func Test...
The third is to use fmt.Fprintf
with an io.Writer
that is os.Stdout
in production code, but bytes.Buffer
in tests.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With