Go Foundations·Clarity, then concurrency

Testing and benchmarks

Write table tests, run the race detector and measure performance with benchmarks.

Beginner 13 min read Lesson 4 of 300 Challenge included
What you will be able to do
  • Write test functions that take *testing.T and report failures with t.Errorf.
  • Drive many cases through one loop with a table test.
  • Run go test -race to catch data races.
  • Measure hot paths with a Benchmark function.

In plain English

A test in Go is a function that starts with Test and takes a *testing.T value, which reports failures with methods like t.Errorf. A table test is a slice of cases that you loop over, so many inputs share one piece of test logic. The go test command runs tests in a package, and adding -race enables the race detector, which finds data races where two concurrent operations touch the same value without coordination. A benchmark is a function starting with Benchmark that measures how long an operation takes by running it many times.

Step by step

  1. 1Write a Test function that accepts *testing.T.
  2. 2Build a slice of table cases with inputs and expected results.
  3. 3Loop over cases and fail with t.Errorf when a result is wrong.
  4. 4Run go test and go test -race from the package directory.
  5. 5Add a Benchmark function for code you want to measure.
add_test.goGo
package lessons

import "testing"

func Add(a, b int) int {
    return a + b
}

func TestAdd(t *testing.T) {
    cases := []struct {
        name string
        a    int
        b    int
        want int
    }{
        {"positive", 2, 3, 5},
        {"zero", 0, 0, 0},
        {"negative", -1, 1, 0},
    }

    for _, c := range cases {
        t.Run(c.name, func(t *testing.T) {
            got := Add(c.a, c.b)
            if got != c.want {
                t.Errorf("Add(%d, %d) = %d, want %d", c.a, c.b, got, c.want)
            }
        })
    }
}

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(2, 3)
    }
}

Common mistakes

  • Naming a test without the Test prefix means go test will silently skip it.
  • Calling t.Fatal in a table test without t.Run stops the whole test instead of just one case.
  • Running benchmarks with go test without the -bench flag will not execute them.
  • Skipping the race detector hides data races that only appear under concurrency.
Your turn

Write a table test

Medium

Write a TestDouble that uses a table of cases to check Double(n) returns 2n for at least three inputs, reporting failures with t.Errorf.

GO · starter
func Double(n int) int {
    return n * 2
}

func TestDouble(t *testing.T) {
}
Check your understanding before moving on.
Knowledge checkQuestion 1

What does go test -race detect?

Select an answer to continue
Study tools

Make it yours.

Keep a private note for this lesson, then turn the key ideas into flashcards you can revisit.

Sign in to save notes and flashcards.Both are private to your account and stay with your progress.
Sign in
Finished reading?

Lock in what you just learned.

Mark this lesson complete to save your place and move one step closer to the certificate.

Next: Context and timeouts
Lesson 4 of 300 · 0% of course