Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/golang/go/llms.txt

Use this file to discover all available pages before exploring further.

The go test command automates testing the packages named by import paths. It compiles test files, runs test functions, and reports results.

Overview

Testing is a first-class citizen in Go. The go test command provides built-in support for unit tests, benchmarks, examples, and fuzz tests.

Basic Usage

go test [build/test flags] [packages] [build/test flags & test binary flags]
# Test current package
go test

# Test with verbose output
go test -v

# Test current package (explicit)
go test .

Test Files

Test File Naming

Test files must:
  • End with _test.go
  • Be in the same package directory
  • Not start with _ or .
// mypackage_test.go
package mypackage

import "testing"

func TestInternal(t *testing.T) {
    // Can access unexported functions
    result := internalFunc()
    if result != expected {
        t.Errorf("got %v, want %v", result, expected)
    }
}

Test Modes

Local Directory Mode

Invoked without package arguments:
go test
go test -v
  • Compiles package in current directory
  • Runs test binary immediately
  • Caching is disabled
  • Prints summary after completion

Package List Mode

Invoked with explicit package arguments:
go test ./...
go test example.com/myapp
  • Compiles and tests each listed package
  • Results are cached
  • Prints ‘ok’ for passing tests
  • Shows full output for failures

Common Test Flags

Test Selection

-run
regexp
Run only tests matching regexp
# Run specific test
go test -run TestMyFunction

# Run tests matching pattern
go test -run "Test.*Integration"

# Run subtests
go test -run TestMyFunc/subtest_name
-skip
regexp
Skip tests matching regexp
go test -skip "TestSlow|TestExternal"

Output Control

-v
flag
Verbose output - print all test names and results
go test -v
-json
flag
Output test results as JSON
go test -json
go test -json | tee test-results.json

Test Execution

-count
n
Run each test n times (default: 1)
# Disable test caching
go test -count=1

# Run tests multiple times
go test -count=10
-parallel
n
Maximum number of tests to run in parallel (default: GOMAXPROCS)
go test -parallel 4
-timeout
duration
Timeout for entire test execution (default: 10m)
go test -timeout 30s
go test -timeout 5m
-short
flag
Run in short mode - skip long-running tests
go test -short
In test code:
if testing.Short() {
    t.Skip("skipping test in short mode")
}
-failfast
flag
Stop after first test failure
go test -failfast

Coverage Flags

-cover
flag
Enable coverage analysis
go test -cover
-coverprofile
file
Write coverage profile to file
go test -coverprofile=coverage.out
-covermode
set|count|atomic
Set coverage mode
  • set: boolean (was this line executed?)
  • count: count how many times each line executed
  • atomic: like count, but correct for concurrent tests
go test -covermode=count -coverprofile=coverage.out

Writing Tests

Basic Test Function

1

Create Test File

Create a file ending in _test.go:
// math_test.go
package math

import "testing"
2

Write Test Function

Test functions must start with Test and take *testing.T:
func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5
    
    if result != expected {
        t.Errorf("Add(2, 3) = %d; want %d", result, expected)
    }
}
3

Run Tests

go test
go test -v

Table-Driven Tests

func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive numbers", 2, 3, 5},
        {"negative numbers", -2, -3, -5},
        {"mixed signs", -2, 3, 1},
        {"zeros", 0, 0, 0},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Add(%d, %d) = %d; want %d", 
                    tt.a, tt.b, result, tt.expected)
            }
        })
    }
}
Run specific subtests:
# Run all Add tests
go test -run TestAdd

# Run specific subtest
go test -run TestAdd/positive

Testing Methods

Report error but continue test:
t.Error("something went wrong")
t.Errorf("got %v, want %v", result, expected)
Report error and stop test immediately:
t.Fatal("critical failure")
t.Fatalf("setup failed: %v", err)
Print log output (only shown with -v or on failure):
t.Log("debug information")
t.Logf("processing item %d", i)
Skip test:
if runtime.GOOS == "windows" {
    t.Skip("skipping on Windows")
}
Register cleanup function:
tmpFile, err := os.CreateTemp("", "test")
if err != nil {
    t.Fatal(err)
}
t.Cleanup(func() {
    os.Remove(tmpFile.Name())
})

Benchmarks

Writing Benchmarks

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

func BenchmarkComplexOperation(b *testing.B) {
    // Setup (not timed)
    data := setupData()
    
    b.ResetTimer() // Reset timer after setup
    
    for i := 0; i < b.N; i++ {
        ComplexOperation(data)
    }
}

Running Benchmarks

# Run all benchmarks
go test -bench=.

# Run specific benchmark
go test -bench=BenchmarkAdd

# Run benchmarks matching pattern
go test -bench="Complex.*"

Examples

Writing Examples

func ExampleAdd() {
    result := Add(2, 3)
    fmt.Println(result)
    // Output: 5
}

func ExampleAdd_negative() {
    result := Add(-2, -3)
    fmt.Println(result)
    // Output: -5
}

func ExamplePerson_String() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)
    // Output: Alice (30 years old)
}
Examples serve as both documentation and tests.

Code Coverage

1

Generate Coverage Profile

go test -coverprofile=coverage.out
2

View Coverage Report

# Text summary
go tool cover -func=coverage.out

# HTML visualization
go tool cover -html=coverage.out
3

Coverage for Multiple Packages

go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Coverage Options

# Specify packages to cover
go test -coverpkg=./... -coverprofile=coverage.out

# Different coverage modes
go test -covermode=set -coverprofile=coverage.out
go test -covermode=count -coverprofile=coverage.out
go test -covermode=atomic -coverprofile=coverage.out

Test Caching

Go caches successful test results to avoid unnecessary reruns.

Cacheable Flags

Tests are cached when using only these flags:
  • -benchtime
  • -cpu
  • -coverprofile
  • -failfast
  • -fullpath
  • -list
  • -outputdir
  • -parallel
  • -run
  • -short
  • -skip
  • -timeout
  • -v

Disabling Cache

# Idiomatic way to disable cache
go test -count=1

Advanced Testing

Setup and Teardown

func TestMain(m *testing.M) {
    // Setup before all tests
    setup()
    
    // Run tests
    code := m.Run()
    
    // Teardown after all tests
    teardown()
    
    os.Exit(code)
}

Parallel Tests

func TestParallel(t *testing.T) {
    t.Parallel() // Mark test as parallelizable
    
    // Test code here
}

func TestParallelSubtests(t *testing.T) {
    tests := []struct{
        name string
        // ...
    }{
        // test cases
    }
    
    for _, tt := range tests {
        tt := tt // Capture range variable
        t.Run(tt.name, func(t *testing.T) {
            t.Parallel()
            // Subtest code
        })
    }
}

Using testdata Directory

mypackage/
  ├── myfile.go
  ├── myfile_test.go
  └── testdata/
      ├── input.json
      └── expected.txt
func TestWithTestdata(t *testing.T) {
    data, err := os.ReadFile("testdata/input.json")
    if err != nil {
        t.Fatal(err)
    }
    // Use data in test
}

Test Compilation

Compile Test Binary

# Compile but don't run
go test -c

# Compile with custom output name
go test -c -o mytest.test

# Run compiled test binary
./mytest.test
./mytest.test -test.v -test.run TestSpecific

Binary Flags

Compiled test binaries accept -test.* flags:
./mytest.test -test.v
./mytest.test -test.run TestMyFunc
./mytest.test -test.bench=.
./mytest.test -test.cpuprofile=cpu.prof

CI/CD Integration

GitHub Actions

.github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-go@v5
        with:
          go-version: '1.21'
      
      - name: Run tests
        run: go test -v -race -coverprofile=coverage.out ./...
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage.out

Makefile

.PHONY: test
test:
	go test -v -race -coverprofile=coverage.out ./...

.PHONY: test-short
test-short:
	go test -short ./...

.PHONY: coverage
coverage: test
	go tool cover -html=coverage.out

.PHONY: bench
bench:
	go test -bench=. -benchmem ./...

Troubleshooting

# Disable caching
go test -count=1

# Or clear cache
go clean -testcache
# Increase timeout
go test -timeout 30m

# Check for infinite loops or deadlocks
go test -timeout 10s -v
# Run with race detector
go test -race

# May need more memory
GORACE="history_size=7" go test -race

See Also

go Command

Overview of go command

Building

Building Go programs

Benchmarking

Performance testing