liveBook · Manning

Testing.T.Run

As explained in Go by Example

testing.T.Run is a Go testing API method that executes a named subtest and reports its result independently.

testing.T.Run executes a named subtest with its own *testing.T value. Each subtest runs independently, so one fatal failure does not prevent other cases from running. section 2.5.1 section 2.5.3

Use Run inside a table-driven test to give every case a readable name and a closure containing its test logic. The closure can access the current case variables and call Fatalf or Errorf through its private *T. section 2.5.2 section 2.5.3

Table-driven subtests

func TestParseSubtests(t *testing.T) { for _, tt := range parseTests { t.Run(tt.name, func(t *testing.T) { got, err := Parse(tt.uri) if err != nil { t.Fatalf("Parse(%q) err = %v", tt.uri, err) } if *got != *tt.want { t.Errorf("got %#v, want %#v", got, tt.want) } }) } } Place shared setup and teardown around the loop when every subtest uses the same resources. section 2.5.2

The parent test waits for its subtests when they run sequentially, while failures remain isolated. Names also make reports readable and let go test select an individual subtest with a filter such as TestParseSubtests/full. section 2.5.4

Listing 2.10 Table-driven subtests (url/url_test.go)
var parseTests = []struct {
    . . .
}{
    {
        name: "with_data_scheme",
        . . .
    },
    {
        name: "full",
        . . .
    },
    {
        name: "without_path",
        . . .
    },
}

func TestParseSubtests(t *testing.T) {
    // We can put common test setup and teardown logic here.

    for _, tt := range parseTests {
        t.Run(tt.name, func(t *testing.T) {  #1
            got, err := Parse(tt.uri)
            if err != nil {
                t.Fatalf(
                    "Parse(%q) err = %v, want <nil>",
                    tt.uri, err,
                )
            }
            if *got != *tt.want {
                t.Errorf(
                    "Parse(%q)\ngot  %#v\nwant %#v",
                    tt.uri, got, tt.want,
                )
            }
        })
    }
}

Inspect the complete table-driven subtest implementation, including named cases, closures, assertions, and shared setup placement. section 2.5.2

How Go by Example covers it

How deep it goes
Explains naming, closures, goroutines, failure isolation, shared setup, and filtering, but not the API signature in detail.
Examples
Demonstrates URL parsing cases named with_data_scheme, full, and without_path, then filters the full subtest with go test.
What it assumes
Assumes familiarity with Go test functions and table-driven cases while defining the closures used to wrap each subtest.
What you can do after
Apply it via Go's testing package to build resilient table-driven tests with readable reports and selective execution.
How it connects
Connects subtests with table-driven testing, closures, goroutines, test reports, and Fatalf or Errorf.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.