Writing effective Unit Tests in Golang


(FistOfJustice) #1

Hello,

I have to say that I am a complete n00b when it comes to running tests in golang. Let’s say for instance I have this piece of code in one file:

    func getJSON(body []byte) (models.Jsonrepo, error) {
	    var s = make(models.Jsonrepo, 0)
	    err := json.Unmarshal(body, &s)
	    if err != nil {
		   log.Fatal(err)
	    }
	    return s, err
    }

How would one write a unit test for it to make sure that it is returning what it should return (which in this case is a slice of struct and an error (jsonrepo is of type slice of struct).


(Kyle Wood) #2

In general, when writing unit tests you want to verify that for some given correct input, correct or valid output is returned. It is also useful to test that for some given incorrect input, the function returns, logs, or errors correctly in response.

To write tests in go, create a file called somefile_test.go. Say your function is in json.go, you should call your test file json_test.go. When you run go test, it will automatically run your tests from that test file.

My first advice would be to return nil, err after your if err != nil { check, instead of logging it. this is better design and will make testing better.

import "testing"

func TestGetJSON(t *testing.T) {
    goodInput := SomeCorrectInput()
    expectedOutput := models.JsonRepo{/*expected values from above input*/}

    out, err := getJSON(goodInput)
    if err != nil {
        t.Fatal("Failure message", err)
    }

    if !reflect.DeepEqual(expectedOutput, out) {
        t.Fatal("Actual output doesn't match expected")
    }
}

With a function signature matching that pattern, you can write simple tests like that. Obviously I’m not covering any error cases, or dealing with real inputs, or using good error messages, but this structure should work for you. You can also use an assertion framework to clean up some of that code, such as testify. An assertion framework is a good idea because when comparing two things which should be equal (expected vs actual output) it will print out the parameters for you, showing you what is different.