为 Stdin 交互编写 Go 测试
在软件测试中,通常需要编写与标准输入流 stdin 交互的测试。当测试从控制台或用户界面读取输入的应用程序时,这一点尤其重要。
考虑以下 Go 应用程序,它从 stdin 读取行并将其回显到 stdout:
<code class="go">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)) } }</code>
要测试此应用程序,可以编写一个测试用例来模拟用户输入并将结果与预期输出进行比较:
<code class="go">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() }</code>
但是,此测试可能会失败并出现错误:“Wanted: abc, Got: --- FAIL: TestInput (3.32s)"。
要解决此问题,请考虑以下解决方案:
不要直接在主函数中操作 stdin 和 stdout,而是定义一个单独的函数接受 io.Reader 和 io.Writer 作为参数并执行所需的操作。然后main函数就可以调用这个函数了,这样测试起来就更方便了。
比如创建一个名为Echo的函数:
<code class="go">func Echo(reader io.Reader, writer io.Writer) { reader := bufio.NewReader(reader) for { fmt.Print("> ", writer) bytes, _, err := reader.ReadLine() if err == io.EOF { return } fmt.Println(string(bytes), writer) } }</code>
在测试中,直接调用Echo函数,而不是与 stdin 和 stdout 交互:
<code class="go">// ... func TestInput(t *testing.T) { inputReader := strings.NewReader("abc\n") outputWriter := new(bytes.Buffer) Echo(inputReader, outputWriter) result := outputWriter.String() if input != result { t.Errorf("Wanted: %v, Got: %v", input, result) } }</code>
此测试现在应该通过,因为它直接测试 Echo 函数,而不依赖于 stdin 和 stdout 操作。
以上是如何测试与标准输入(Stdin)交互的 Go 应用程序?的详细内容。更多信息请关注PHP中文网其他相关文章!