liveBook · Manning

Go test

As explained in Learn Go with Pocket-Sized Projects

The Go test framework is the standard framework that discovers, executes, and reports Go package tests.

Run `go test` in the current directory to execute its Go tests. A successful run can report `PASS` and an `ok` line for the tested package. Keep tests alongside changes so you can rerun them after even a small edit; a passing test checks the cases you wrote, not every possible behavior. section 2.1.2 section 2.6

For printed output, write an `Example` function with a `// Output:` comment followed by the expected lines. The test utility compares those lines with what the function prints. Without `// Output:`, the example can still appear in documentation, but it is not executed as a test. section 2.1.2

Listing 2.2 main_internal_test.go: Testing the printed output
package main

func Example_main() {
    main() #1
    // Output: #2
    // Hello world
}

This example calls `main` and supplies the expected `Hello world` output for the test utility to check. section 2.1.2

To test a function’s return value, use a `Test` function that accepts `*testing.T`: set `want`, call the function for `got`, compare them, and call `t.Errorf` if they differ. Rerun `go test` after changing `want` to see the failure. Keeping the function under test narrow also makes it easier to test and debug. section 2.1.4

Listing 2.4 main_internal_test.go: Testing greet
package main

import "testing"

func TestGreet(t *testing.T) {
    want := "Hello world"

    got := greet()

    if got != want {
        // mark this test as failed
        t.Errorf("expected: %q, got: %q", want, got)
    }
}

`TestGreet` compares an expected string with `greet()` and reports a mismatch through `t.Errorf`. section 2.1.4

For independent tests, `t.Parallel()` lets tests in the same scope run alongside others marked the same way. That can shorten a run, but a plain `go test` result can look fine even when concurrent writes are suspected of racing; do not treat that result as proof that shared data is safe. section 7.3.2

Listing 7.10 Cooking example using t.Parallel()
func TestCache_Parallel(t *testing.T) {
    c := cache.New[int, string]() #1

    t.Run("write six", func(t *testing.T) {
        t.Parallel() #2
        c.Upsert(6, "six")
    })

    t.Run("write kuus", func(t *testing.T) {
        t.Parallel() #3
        c.Upsert(6, "kuus")
    })
}

Two parallel subtests write different values to the same cache index, making concurrent access the issue to investigate. section 7.3.2

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Shows the command, output checks, testing.T failures, and parallel execution, but does not show how to detect the suspected race.
Examples
Uses a printed greeting, a string-returning greeting function, and parallel writes to one cache index.
What it assumes
Assumes a Go function to test while introducing Example output comments, test-function conventions, and testing.T.
What you can do after
Operate/configure it to rerun tests, verify Example output, and see failures reported with testing.T.
How it connects
Connects Example functions, the testing package, table-driven tests, documentation, and parallel tests.

Also explained in

Compare how 4 books explain go test →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.