0Pricing
Go Academy · Lesson

Table-Driven Tests

Parameterized tests with subtests

Table-Driven Tests is a free Go Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What are table-driven tests?

Table-driven tests define a slice of test cases (inputs and expected outputs) and loop over them with a single test body. They reduce duplication and make adding cases trivial.

Basic pattern

Define a struct for each case, loop with t.Run, and report failures with the case name:

tests := []struct {
    name  string
    input int
    want  int
}{
    {"zero", 0, 0},
    {"positive", 3, 9},
    {"negative", -2, 4},
}
for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {
        got := Square(tt.input)
        if got != tt.want {
            t.Errorf("Square(%d) = %d; want %d", tt.input, got, tt.want)
        }
    })
}

Anonymous struct slice

Use an anonymous struct for the test case type — it keeps the case definition close to the test and avoids naming a one-use type.

Including error cases

Add a wantErr bool field to test that functions return errors in the expected scenarios:

{"invalid input", -1, 0, true},
// in the loop:
if (err != nil) != tt.wantErr {
    t.Errorf("wantErr %v, got err %v", tt.wantErr, err)
}

Naming subtests

A descriptive name field makes failures self-explanatory. You can run a specific case with -run TestFunc/case_name.

t.Run parallel subtests

Mark each subtest parallel and capture the loop variable to run cases concurrently (important when tests are I/O-bound).

for _, tt := range tests {
    tt := tt // capture
    t.Run(tt.name, func(t *testing.T) {
        t.Parallel()
        // ...
    })
}

Shared setup per case

Use tt.setup function fields to allow per-case setup without duplicating boilerplate:

type tc struct {
    setup func() *DB
    input string
    want  int
}

Keeping cases readable

If cases grow large, define them as named variables or load them from testdata files. Keep the table compact — one line per case when possible.

Testing multiple outputs

Table test functions that return multiple values by adding a field per output:

type tc struct {
    input     string
    wantVal   int
    wantErr   bool
}

Testify assert in tables

Use github.com/stretchr/testify/assert inside table tests for readable assertions without verbose if/t.Errorf blocks.

assert.Equal(t, tt.want, got, tt.name)

Documenting with cases

The table of cases serves as living documentation. Future developers read it to understand all supported inputs and edge cases at a glance.

Quick Check

Why do you capture the loop variable (tt := tt) before t.Parallel in table-driven tests?

Recap: Table-Driven Tests

Key points:

  • Slice of structs covering inputs, expected outputs, and error flag
  • Loop with t.Run for named, independent subtests
  • Capture loop variable (tt := tt) before t.Parallel
  • Cases serve as living documentation of supported behaviours

Frequently asked questions

Is the “Table-Driven Tests” lesson free?

Yes — the full text of “Table-Driven Tests” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.

What will I learn in “Table-Driven Tests”?

Parameterized tests with subtests You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Go Academy?

No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Table-Driven Tests” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Go Academy lesson?

Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Writing Unit Tests with testing
  2. Table-Driven Tests
  3. Test Doubles: Mocks and Stubs
  4. Test Coverage and testify
← Back to Go Academy