DEV Community

Shaikhul Islam
Shaikhul Islam

Posted on

Testing in Go

Go testing support is awesome. It has a subcommand go test that looks for *_test.go files in package folder and run all test functions that starts with Test* prefix and report success or error.

All test functions should follow this naming convention

func TestXXXX(t *testing.T) {

}
Enter fullscreen mode Exit fullscreen mode

t param is used to report success/failure messages. Some useful methods are

t.Errorf    // to report an error
t.Logf      // to log something
t.Skip      // skip a test
Enter fullscreen mode Exit fullscreen mode

More on testing package are here

Say, we have a package hello that defines a simple Hello function as follows that we want to add test

// file hello.go
package hello

func Hello() string {
  return "Hello World"
}
Enter fullscreen mode Exit fullscreen mode

We need to create hello_test.go file in same directory

// file hello_test.go
package hello

// import testing package
import "testing"

func TestHello(t *testing.T) {
  want := "Hello World"
  if got := Hello(); got != want {
    // report mismatch
    t.Errorf("Hello() = %q, want %q", got, want)
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we have tests for our hello package. To test we need go to the folder hello/

$ ls
hello.go  hello_test.go
Enter fullscreen mode Exit fullscreen mode

If we do go test it will run the test runner and execute all Test* functions and report success/error

$ go test
PASS
ok      main/hello  0.011s
Enter fullscreen mode Exit fullscreen mode

To see which tests were run we can use verbose option go test -v

$ go test -v
=== RUN   TestHello
--- PASS: TestHello (0.00s)
PASS
ok      main/hello  0.029s
Enter fullscreen mode Exit fullscreen mode

We can also specify a substring of specific test function go test -v -run="Hello" and test runner will look for test functions that uses the substring

$ go test -v -run="Hello"
=== RUN   TestHello
--- PASS: TestHello (0.00s)
PASS
ok      main/hello  0.027s
Enter fullscreen mode Exit fullscreen mode

Table driven Testing

We added a new Greet function that takes a param and return a greet message

func Greet(name string) string {
  return fmt.Sprintf("Hello %s", name)
}
Enter fullscreen mode Exit fullscreen mode

and we want to test this Greet function but with many test cases, we can create a slice of struct with input, output definition and check results in a loop. This is called table driven testing.

func TestGreet(t *testing.T) {
  testCases := []struct {
    testDesc string
    input string
    output string
  } {
    {"Empty string", "", "Hello "},
    {"ASCII string", "World", "Hello World"},
    {"Unicode string", "δΈ–η•Œ", "Hello δΈ–η•Œ"},
  }
  for _, testCase := range testCases {
    t.Run(testCase.testDesc, func(t *testing.T) {
      if got := Greet(testCase.input); got != testCase.output {
        t.Errorf("Hello() = %q, want %q", got, testCase.output)
      }
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Here we uses an anonymous struct that has testDest, input and output fields, and then we create a slice of struct with our test cases.
t.Run takes an anynymous function which is similar to our TestHello function.

Go does not provide any built assertion library but there are plenty out there to import. one is testify/assert

Once we import it from github.com/stretchr/testify/assert we can use differnt assertion functions like these

assert.Equal(t, expected, actual)
assert.NotEqual(t, expected, actual)
assert.True(t, boolStmt)
assert.False(t, boolStmt)
Enter fullscreen mode Exit fullscreen mode

We can run tests against this test as go test -v -run="Greet"

$ go test -v -run="Greet"
=== RUN   TestGreet
=== RUN   TestGreet/Empty_string
=== RUN   TestGreet/ASCII_string
=== RUN   TestGreet/Unicode_string
--- PASS: TestGreet (0.00s)
    --- PASS: TestGreet/Empty_string (0.00s)
    --- PASS: TestGreet/ASCII_string (0.00s)
    --- PASS: TestGreet/Unicode_string (0.00s)
PASS
ok      main/hello  0.009s
Enter fullscreen mode Exit fullscreen mode

Cool! here we can see the breakdown of which tests were run with the test description.

Full examples are given in this repl link

Top comments (0)