How to test a Go function which runs a command?

Kurt Peek :

Following the example at https://golang.org/pkg/os/exec/#Cmd.StdoutPipe, suppose I have a function getPerson() defined like so:

package stdoutexample

import (
    "encoding/json"
    "os/exec"
)

// Person represents a person
type Person struct {
    Name string
    Age  int
}

func getPerson() (Person, error) {
    person := Person{}
    cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`)
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        return person, err
    }
    if err := cmd.Start(); err != nil {
        return person, err
    }
    if err := json.NewDecoder(stdout).Decode(&person); err != nil {
        return person, err
    }
    if err := cmd.Wait(); err != nil {
        return person, err
    }
    return person, nil
}

In my 'real' application, the command run can have different outputs, I'd like to write test cases for each of these scenarios. However, I'm not sure how to go about this.

So far all I have is a test case for one case:

package stdoutexample

import (
    "testing"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
)

func TestGetPerson(t *testing.T) {
    person, err := getPerson()
    require.NoError(t, err)
    assert.Equal(t, person.Name, "Bob")
    assert.Equal(t, person.Age, 32)
}

Perhaps the way to go about this is to split this function into two parts, one which writes the output of the command to a string, and another which decodes the output of a string?

Sufiyan Parkar :

adding to https://stackoverflow.com/a/58107208/9353289,

Instead of writing separate Test functions for every test, I suggest you use a Table Driven Test approach instead. Here is an example,

func Test_getPerson(t *testing.T) {
    tests := []struct {
        name          string
        commandOutput []byte
        want          Person
    }{
        {
            name:          "Get Bob",
            commandOutput: []byte(`{"Name": "Bob", "Age": 32}`),
            want: Person{
                Name: "Bob",
                Age:  32,
            },
        },

        {
            name:          "Get Alice",
            commandOutput: []byte(`{"Name": "Alice", "Age": 25}`),
            want: Person{
                Name: "Alice",
                Age:  25,
            },
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := getPerson(tt.commandOutput)
            require.NoError(t, err)
            assert.Equal(t, tt.want.Name, got.Name)
            assert.Equal(t, tt.want.Age, got.Age)

        })
    }
}

Simply adding test cases to the slice, will run all test cases.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to create a static Go binary which runs on every distro?

How to write a for loop which runs an asynchronous command in each iteration?

How to pass ArrayList to Invoke-Command which runs on remote machine

How to test a function which include an async function?

How to test function which returns function with parameters?

In R, how to write function that runs t-test on list of dataframes

How to unit test a function which as viewchild

How to test a function which returns a promise $q?

How to test a function which has a setTimeout with jasmine?

How to test utility function which creates a file

Jest how to test the line which calls a function?

How to test a unexported (private) function in go (golang)?

How to unit test a Go Gin handler function?

R which function runs another function

How to test if command is alias, function or binary?

How to test a function which returns void in google test?

How to create a test server which uses TLS client authentication in Go?

How to call Go function of test1 in test2

How can I create a windows 10 script which runs a command under specified path?

How to test a function which calls async function using Jasmine

How to test a function which returns anonymous function in jest?

Function which runs lm over different variables

Is it possible to specify which overloaded function runs in Java

Kotlin Coroutines: on which thread the suspend function runs on?

Why my AWS Lambda function doesn't wait for SSM Send Command (which runs Shell script remotely on EC2) to complete?

Creating a function that runs arbitrary shell commands in Go

How to define a function type which accepts any number of arguments in Go?

How to write a function which accepts its own output as input and runs in a loop until a condition is met?

Mocha/angular unit test never runs 'then' function

TOP Ranking

HotTag

Archive