Home  >  Article  >  Backend Development  >  How to test nested input in Go

How to test nested input in Go

王林
王林forward
2024-02-14 12:00:11985browse

如何在 Go 中测试嵌套输入

php editor Youzi introduces you how to test nested input in Go. When writing Go code, you often encounter situations where you need to handle nested input, such as nested JSON data or multi-dimensional arrays. How to effectively test these nested inputs is a key issue. This article will show you some practical methods and techniques to help you easily test nested inputs in Go and ensure the correctness and stability of your code. Whether you are a beginner or an experienced developer, these tips will be very helpful when writing and testing Go code. Let’s find out together!

Question content

I have the function of using os.stdin to obtain user input

func (i input) getinput(stdin io.reader) (string, error) {
    reader := bufio.newreader(stdin)

    data, err := reader.readstring('\n')
    if err != nil {
        return "", fmt.errorf("get input error: %w", err)
    }

    return strings.replaceall(data, "\n", ""), nil
}

In my program, I need to have 2 inputs:

  • First used to obtain basic information, such as username
  • The second one is used to get additional information that depends on the first input
name,err := getinput(os.stdin)
if err != nil {
 // error handling.....
}

switch name {
  case "test":
    //do something...
    age, err := getinput(os.stdin)
    if err != nil {
      // error handling.....
    }
    fmt.println(age)

  case "another":
    // here another input
}

Is it possible to write a unit test for this situation? To test a user input, I used this code snippet and it worked:

    var stdin bytes.Buffer
    stdin.Write([]byte(fmt.Sprintf("%s\n", tt.input)))
    GetInput(stdin)

But it doesn't work with 2 nested inputs

Workaround

Maybe consider using a function that returns a specific type of result and putting it into a separate package.

Since I see name and age mentioned, maybe we can assume a concrete type such as person to illustrate.

Note that we want to include the actual reader as a parameter, rather than having a hardcoded reference to os.stdin. This makes simulation of nested inputs possible in the first place.

In this way, the signature of the method might look like this:

func nestedinput(input io.reader) (*person, error)

The corresponding type can be:

type person struct {
    name string
    age  int
}

If you now merged your code snippets into a complete go file, in a separate directory with the name input.go, it might look like this:

package input

import (
    "bufio"
    "fmt"
    "io"
    "strconv"
    "strings"
)

func getinput(reader *bufio.reader) (string, error) {
    data, err := reader.readstring('\n')
    if err != nil {
        return "", fmt.errorf("get input error: %w", err)
    }

    return strings.replaceall(data, "\n", ""), nil
}

type person struct {
    name string
    age  int
}

func nestedinput(input io.reader) (*person, error) {
    reader := bufio.newreader(input)
    name, err := getinput(reader)
    if err != nil {
        return nil, err
    }

    switch name {
    case "q":
        return nil, nil
    default:
        agestr, err := getinput(reader)
        if err != nil {
            return nil, err
        }
        age, err := strconv.atoi(agestr)
        if err != nil {
            return nil, err
        }
        return &person{name: name, age: age}, nil
    }
}
The input of

q returns nil, nil and can be used to terminate the input, for example if the query is made in a loop.

unit test

unit test

func test_nestedinput(t *testing.t)

A file named input_test.go should now provide the input data.

Since the nestedinput function now requires io.reader as a parameter, we can simply generate the required input, e.g.

input := strings.newreader("george\n26\n")

So the test might look like this:

package input

import (
    "strings"
    "testing"
)

func Test_nestedInput(t *testing.T) {
    input := strings.NewReader("George\n26\n")
    person, err := NestedInput(input)
    if err != nil {
        t.Error("nested input failed")
    }
    if person == nil {
        t.Errorf("expected person, but got nil")
        return
    }
    if person.Name != "George" {
        t.Errorf("wrong name %s, expected 'George'", person.Name)
    }
    if person.Age != 26 {
        t.Errorf("wrong age %d, expected 26", person.Age)
    }
}

Of course, the test can be extended with more details. However, as you can see, this simulates nested input.

The above is the detailed content of How to test nested input in Go. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete