如何编写写入stdin的Go测试?

时间:2016-05-16 14:53:19

标签: unit-testing go

假设我有一个简单的应用程序,它从stdin读取行并简单地将其回送到stdout。例如:

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))
    }
}

我想编写一个写入stdin的测试用例,然后将输出与输入进行比较。例如:

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()
}

正在运行go test -v会给我以下内容:

=== RUN   TestInput
--- FAIL: TestInput (3.32s)
    echo_test.go:25: Wanted: abc
        , Got: --- FAIL: TestInput (3.32s)
FAIL
exit status 1

我显然在这里做错了。我该如何测试这类代码呢?

2 个答案:

答案 0 :(得分:5)

您可以定义一个以mainstdin作为参数的函数,而不是使用stdoutio.Readerio.Writer中执行所有操作无论你想做什么。然后main可以调用该函数,您的测试函数可以直接测试该函数。

答案 1 :(得分:3)

这是一个写入stdin并从stdout读取的示例。请注意,它不起作用,因为输出包含"> "首先。不过,您可以根据自己的需要进行修改。

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()
}