Golang testing guide w/ Golang benchmarking

Golang testing guide w/ Golang benchmarking

Advent Calendar #23

Over the course of the past few days I've been working on a simple "microservice" framework. Although it's not the real one you might have in your head, the actual point of the post remains the same. I've tried Golang and here's what I've learned about testing.

1st of: Golang is pretty awesome.

I have been working with go previously, for a simple card game (cards against humanity clone).

And after a few hours it felt like I've been programming in Go for quite a long time.

Minimal testing utils come preinstalled

That means, we do not have to install any further packages just to run go test .

Stuck? READ THIS IF YOUR TEST ISN'T RUN

Go recognizes test cases in files that look like this

anything_test.go.

If the name of your file does not match, IT WON'T RUN!

Furthermore, your methods have to follow a specific pattern too!

func TestAnythingThatYouWant(t *testing.T) { // You NEED the "Test" prefix
  t.Error("Error here.") // test fails, if not called at all -> test success
}

And you need the t *testing.T, but that's something the go compiler tells you if you have your method prefixed with Test , at least.

Benchmarking

I needed to measure the performance between two function implementations, so I created two functions with the same signature and started googling for how to benchmark stuff in go.

It turned out, it's quite simple, and is part of the standard testing tools aswell.

For benchmarking, create a function, THAT IS PREFIXED WITH Benchmark (Otherwise it won't work), and with the signature b *testing.B . Missing this step will lead to either unrun benchmark tests, or errors.

YOU NEED TO RUN go test -bench . to actually run the benchmark tests!!!

Example

// counting_test.go

func BenchmarkCount(b *testing.B) {
  for n := 0; n < b.N; n++ {
    // do your benchmark code here.
  }
}

NOTE! n is not a loop that you specify. It's something that comes from the golang testing utils to get an average measurement.

I thought it's something that I can use freely, but it's not. My benchmark looked like this in the end

func BenchmarkThousandRoutes(b *testing.B) {

    for n := 0; n < b.N; n++ {
        routeDefinitions := []Route{}
        // create thousand routes
        for i := 0; i != 1000; i++ {
            routeDefinitions = append(routeDefinitions, MakeRoute("/test/"+strconv.Itoa(n)+"/{id}", "get", nil))
        }
        FindRouteForV2(routeDefinitions, "/test/900/3", "GET")
    }
}