testctxlint

package module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2025 License: MIT Imports: 14 Imported by: 0

README

testctxlint logo
testctxlint

Go Reference

A Go linter that detects usage of context.Background() and context.TODO() in test functions and suggests using t.Context() or b.Context() instead. The linter detects problematic context usage in test functions, their subtests, and goroutines launched from tests.

Built using Go's analysis framework, testctxlint integrates seamlessly with existing Go tooling and provides automatic fixes for detected issues.

Why use test contexts?

Go 1.24 introduced t.Context() and b.Context() methods for *testing.T and *testing.B respectively (see Go 1.24 changelog). These provide contexts that are automatically cancelled when the test finishes, making them more appropriate for test scenarios than context.Background() or context.TODO().

Installation

CLI Tool

Using go install
go install github.com/icedream/testctxlint/cmd/testctxlint@latest
Using pre-built binaries

Download the appropriate binary for your platform from the releases page.

Requirements

  • Go 1.24 or later (required for t.Context() and b.Context() methods)

Usage

Command Line

Basic usage:

testctxlint ./...

Check a specific package:

testctxlint ./pkg/mypackage

Apply suggested fixes automatically:

testctxlint -fix ./...

Show fixes as a diff without applying them:

testctxlint -diff ./...

Get help:

testctxlint -help
Sample Output

When testctxlint finds issues, it provides clear messages and suggestions:

/path/to/file.go:15:9: call to context.Background from a test routine
/path/to/file.go:23:11: call to context.TODO from a test routine

With the -fix flag, it can automatically apply the suggested fixes:

// Before
ctx := context.Background()

// After
ctx := t.Context()

Programmatic Usage

package main

import (
    "golang.org/x/tools/go/analysis"
    "golang.org/x/tools/go/analysis/singlechecker"
    "github.com/icedream/testctxlint"
)

func main() {
    // Use the analyzer directly
    singlechecker.Main(testctxlint.Analyzer)
}

Or integrate with other analyzers:

package main

import (
    "golang.org/x/tools/go/analysis/multichecker"
    "github.com/icedream/testctxlint"
    // ... other analyzers
)

func main() {
    multichecker.Main(
        testctxlint.Analyzer,
        // ... other analyzers
    )
}

Examples

❌ Bad: Using context.Background() or context.TODO()

func TestSomething(t *testing.T) {
    // BAD: Using context.Background() in test
    ctx := context.Background()
    doSomething(ctx)
    
    // BAD: Using context.TODO() in test
    doSomethingElse(context.TODO())
    
    // BAD: In subroutines
    t.Run("subtest", func(t *testing.T) {
        ctx := context.Background() // This will be flagged
        doSomething(ctx)
    })
    
    // BAD: In goroutines
    go func() {
        ctx := context.TODO() // This will be flagged
        doSomething(ctx)
    }()
}

func BenchmarkSomething(b *testing.B) {
    // BAD: Using context.Background() in benchmark
    ctx := context.Background()
    for i := 0; i < b.N; i++ {
        doSomething(ctx)
    }
}

✅ Good: Using t.Context() or b.Context()

func TestSomething(t *testing.T) {
    // GOOD: Using t.Context() in test
    ctx := t.Context()
    doSomething(ctx)
    
    // GOOD: Direct usage
    doSomethingElse(t.Context())
    
    // GOOD: In subroutines
    t.Run("subtest", func(t *testing.T) {
        ctx := t.Context() // Properly scoped test context
        doSomething(ctx)
    })
    
    // GOOD: In goroutines (though be careful with goroutines in tests)
    go func() {
        ctx := t.Context() // Uses the test context
        doSomething(ctx)
    }()
}

func BenchmarkSomething(b *testing.B) {
    // GOOD: Using b.Context() in benchmark
    ctx := b.Context()
    for i := 0; i < b.N; i++ {
        doSomething(ctx)
    }
}

Integration

With golangci-lint

Currently, testctxlint is not included in golangci-lint by default. You can run it separately or create a custom linter configuration.

With IDEs

Most Go IDEs that support the Go analysis framework should be able to use testctxlint. The exact integration method depends on your IDE.

In CI/CD

Using go install
# Install and run in CI
go install github.com/icedream/testctxlint/cmd/testctxlint@latest
testctxlint ./...
Using pre-built binaries
# Download and extract pre-built binary
curl -L -o testctxlint.tar.gz https://github.com/icedream/testctxlint/releases/latest/download/testctxlint_linux_x86_64.tar.gz
tar -xzf testctxlint.tar.gz
./testctxlint ./...

Benchmarking

The project includes performance benchmarks that can be used to monitor performance regressions:

Running Benchmarks Locally

# Run benchmarks
go test -bench=. -benchmem

# Run benchmarks multiple times for statistical analysis
go test -bench=. -benchmem -count=5

# Compare benchmark results using benchstat
go install golang.org/x/perf/cmd/benchstat@latest
go test -bench=. -benchmem -count=5 | tee new.txt
# (make changes to code)
go test -bench=. -benchmem -count=5 | tee old.txt
benchstat old.txt new.txt

Automated Benchmark Comparison

The repository includes a GitHub Actions workflow that automatically compares benchmark performance between the main branch and pull requests. When you open a PR:

  1. Benchmarks are run on both the main branch and your PR branch
  2. Performance differences are calculated using benchstat
  3. Results are posted as a comment on the PR
  4. Benchmark data is stored as artifacts for historical analysis

The benchmark comparison helps identify performance regressions and improvements, providing metrics for:

  • Execution time (ns/op): How long operations take
  • Memory usage (B/op): Bytes allocated per operation
  • Allocations (allocs/op): Number of memory allocations per operation

Testing

You can run the usual go test commands to run the tests in this repository.

Additionally, we lint our code using golangci-lint v2.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

License

See LICENSE.txt for details on this software's license.

This software incorporates material from third parties. For these portions, see NOTICE.txt for details.

Documentation

Overview

Package testctxlint provides an Analyzer for detecting creation of context where test context can be used instead.

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = &analysis.Analyzer{
	Name:     "testctxlint",
	Doc:      "check for any code where test context could be used but isn't",
	Run:      run,
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	URL:      "https://pkg.go.dev/github.com/icedream/testctxlint",
}

Analyzer is the main instance of the testctxlinter analyzer.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
cmd
testctxlint command
Package main runs the analyzer.
Package main runs the analyzer.
examples
multichecker command
Example application
Example application

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL