5

I am trying to test some functions that print ANSI escape codes. e.g.

// Print a line in a color
func PrintlnColor(color string, a ...interface{}) {
    fmt.Print("\x1b[31m")
    fmt.Print(a...)
    fmt.Println("\x1b[0m")
}

I tried using Examples to do it, but they don't seem to like escape codes.

Is there any way to test what is written to stdout?

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
giodamelio
  • 5,465
  • 14
  • 44
  • 72
  • What's the purpose for testing stdout? It's much easier, to verify that your function produces the output you want before it's written to stdout. – JimB Nov 14 '14 at 20:20
  • The problem is stdout is the only output. The function is going to return `n int, err error` just like `fmt.Println` – giodamelio Nov 14 '14 at 20:34
  • you could replace `os.Stdout` with something akin to a `io.MultiWriter` that returned an `*os.File`, but it's easier to just refactor your code to make it testable. You don't need to test `fmt.Println` and `os.Stdout`, they have their own unit tests. – JimB Nov 14 '14 at 20:47
  • 1
    Yeah, write an `FprintlnColor` and then make `PrintlnColor` call it with `Stdout`. It can write to a `bytes.Buffer` for tests. – twotwotwo Nov 15 '14 at 00:33

1 Answers1

13

Using fmt.Fprint to print to io.Writer lets you control where the output is written.

var out io.Writer = os.Stdout

func main() {
    // write to Stdout
    PrintlnColor("foo")

    buf := &bytes.Buffer{}
    out = buf

    // write  to buffer
    PrintlnColor("foo")

    fmt.Println(buf.String())
}

// Print a line in a color
func PrintlnColor(a ...interface{}) {
    fmt.Fprint(out, "\x1b[31m")
    fmt.Fprint(out, a...)
    fmt.Fprintln(out, "\x1b[0m")
}

Go play

jmaloney
  • 11,580
  • 2
  • 36
  • 29