Testing in Go - udaybhanu007/OVN-Poc GitHub Wiki

1) Introduction to Testing in Go

  1. Full featured testing and profiling tools
  2. Complete API for test execution (like maven in other languages)
  3. Little support for assertions

Test related packages in Go

  1. testing - home for working with testing
  2. testing/quick - specified for blackbox testing
  3. testing/iotest - very specific to reader/writers from an external source
  4. net/http/httptest - network applications like network I/O, including TCP/IP, UDP

Testing libraries outside Go

  1. testify - has good assertion experience
  2. Ginkgo - behavioral driven testing
  3. GoConvey - browser based format than in command line

4. httpexpect - end to end webservices testing, popular for testing rest api

5. gomock - mock your go objects

  1. go-sqlmock - testing with sql mock .

2) Creating and running tests

Naming Conventions

  1. add _test to the file names egs : main_test.go (this does 2 things for us 1. it will get identified by the build tool for testing 2. when creating production builds these files will get excluded from the binaries that are created)
  2. all the functions intended for testing should be prefixed with Test egs : TestFoo
  3. accept one parameter to the test function which is a pointer to testing.T object egs: TestFoo(t *testing.T) (this is to use this object later in the function for example if a failure is reported and hence get access to the test runner)
  4. you can have the test files in the same package as the source code, which will help you do whitebox testing
  5. you can keep all the tests related to a particular package in another package but with a package name _test egs : say your source code is in a package with name main then the tests for that package should be in main_test. This will help you do black box testing

Writing tests

  1. Immediate failure - will exit the test function. t.FailNow() , t.Fatal(args ...interface{}) , t.Fatalf(format string, args ..interface{})
  2. Non-Immediate failure - will continue with the other test functions. t.Fail(), t.Error(args ..interface{}) , t.Errorf(format string, args ..interface{})

Other useful functions All the methods are from golang.org/pkg/testing

  • Log and Logf, Helper, Skip, Skipf, SkipNow, Run, Parallel

There are more..

Sample code for a test

 func TestAddUser(t *testing.T) {
user := &domain.User{
	ID:        7,
	FirstName: "",
	LastName:  "Soy",
	Email:     "Rabb@email",
}
jsonUser, _ := json.Marshal(user)
request, err := http.NewRequest("POST", "/adduser", bytes.NewBuffer(jsonUser))
if err != nil {
	t.Fatal(err)
}
response := httptest.NewRecorder()
helpers.RootHandler(controllers.AddUser).ServeHTTP(response, request)
if response.Result().StatusCode != 200 {
	t.Errorf("expected status %v but got %v", 200, response.Result().StatusCode)
}
}

Running Tests

  1. go test : - Run all tests in the current directory
  2. go test {pkg1} {pkg2} {pkg3} .. {pkgn} :- test specified packages
  3. go test ./... :- run tests in current package and its descendants
  4. go test -v :- verbose output, can be combined with all the other commands
  5. go test -run {regexp} :- run only tests matching {regexp}

BenchMark Tests

Naming Conventions

  1. Prefix tests with "BenchMark"
  2. Accept one parameter *testing.B

Key testing.B Members

  • b.N - no of times the tests needs to be executed
  • b.StartTimer, b.StopTimer, b.ResetTimer
  • b.RunParallel

There are more..

Running Benchmark Tests

  1. go test -bench - run all tests including benchmark tests
  2. go test -bench -benchtime 10s - run benchmark tests targeting specified time

Sample Benchmark Test

func BenchmarkAddUser(b *testing.B) {
for i := 0; i < b.N; i++ {
	user := &domain.User{
		ID:        i + 7,
		FirstName: "acd",
		LastName:  "Soy",
		Email:     "Rabb@email",
	}
	response, err := makeRequestToAddUser(*user)
	if err != nil {
		b.Fatal(err)
	}
	if response.Result().StatusCode != 200 {
		b.Errorf("expected status %v but got %v", 200, response.Result().StatusCode)
	}
}
}

Profiling Tests

  1. go test -benchmem : report memory allocation statistics for benchmarks
  2. go test -trace {trace.out} : record execution trace to {trace.out} for analysis
  3. go test {type} profile {file} : generate profile of requested type : block, cover, cpu, mem, mutex