Say that I have a simple application that reads lines from stdin and simply echoes it back to stdout. For example:
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
bytes, _, err := reader.ReadLine()
if err == io.EOF {
os.Exit(0)
}
fmt.Println(string(bytes))
}
}
I would like to write a test case that writes to stdin and then compares the output to the input. For example:
package main
import (
"bufio"
"io"
"os"
"os/exec"
"testing"
)
func TestInput(t *testing.T) {
subproc := exec.Command(os.Args[0])
stdin, _ := subproc.StdinPipe()
stdout, _ := subproc.StdoutPipe()
defer stdin.Close()
input := "abc\n"
subproc.Start()
io.WriteString(stdin, input)
reader := bufio.NewReader(stdout)
bytes, _, _ := reader.ReadLine()
output := string(bytes)
if input != output {
t.Errorf("Wanted: %v, Got: %v", input, output)
}
subproc.Wait()
}
Running go test -v
gives me the following:
=== RUN TestInput
--- FAIL: TestInput (3.32s)
echo_test.go:25: Wanted: abc
, Got: --- FAIL: TestInput (3.32s)
FAIL
exit status 1
I'm obviously doing something incorrect here. How should I go about testing this type of code?
Instead of doing everything in main
with stdin
and stdout
, you can define a function that takes an io.Reader
and an io.Writer
as parameters and does whatever you want it to do. main
could then call that function and your test function could test that function directly.
Here is an example that writes to stdin and reads from stdout. Note that it does not work because the output contains "> " at first. Still, you can modify it to suit your needs.
func TestInput(t *testing.T) {
subproc := exec.Command("yourCmd")
input := "abc\n"
subproc.Stdin = strings.NewReader(input)
output, _ := subproc.Output()
if input != string(output) {
t.Errorf("Wanted: %v, Got: %v", input, string(output))
}
subproc.Wait()
}
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