Home  >  Article  >  Backend Development  >  How to Test Go Applications That Interact with Standard Input (Stdin)?

How to Test Go Applications That Interact with Standard Input (Stdin)?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-10-27 00:24:02548browse

How to Test Go Applications That Interact with Standard Input (Stdin)?

Writing Go Tests for Stdin Interactions

In software testing, it's often necessary to write tests that interact with stdin, the standard input stream. This is particularly relevant when testing applications that read input from the console or a user interface.

Consider the following Go application that reads lines from stdin and echoes them back to 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>

To test this application, a test case can be written to simulate user input and compare the results to the expected output:

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

However, this test may fail with the error: "Wanted: abc, Got: --- FAIL: TestInput (3.32s)".

To resolve this issue, consider the following solution:

Instead of manipulating stdin and stdout directly in the main function, define a separate function that accepts io.Reader and io.Writer as parameters and performs the desired operations. The main function can then call this function, making it easier to test.

For example, create a function called 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>

In the test, directly call the Echo function instead of interacting with stdin and 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>

This test should now pass, as it directly tests the Echo function without relying on stdin and stdout manipulation.

The above is the detailed content of How to Test Go Applications That Interact with Standard Input (Stdin)?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn