Skip to content

Go static analyzer that reports where you forgot to call t.Helper().

License

Notifications You must be signed in to change notification settings

ichiban/thelper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

thelper

Go static analyzer that reports where you forgot to call t.Helper().

As a command

First, install thelper command via go get.

$ go get github.com/ichiban/thelper/cmd/thelper

Then, run thelper command at your package directory.

$ thelper ./...
/Users/ichiban/src/thelper/testdata/src/a/a_test.go:11:1: unmarked test helper: call t.Helper()
/Users/ichiban/src/thelper/testdata/src/a/a_test.go:25:1: unmarked test helper: call s.Helper()

As an analysis.Analyzer

First, install the package via go get.

$ go get github.com/ichiban/thelper

Then, include thelper.Analyzer in your checker.

package main

import (
	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/multichecker"
	"golang.org/x/tools/go/analysis/passes/nilfunc"
	"golang.org/x/tools/go/analysis/passes/printf"
	"golang.org/x/tools/go/analysis/passes/shift"

	"github.com/ichiban/thelper"
)

func main() {
	multichecker.Main(
		// other analyzers of your choice
		nilfunc.Analyzer,
		printf.Analyzer,
		shift.Analyzer,

		thelper.Analyzer,
	)
}

What happens if I don't call t.Helper()?

go test shows FAILs with an unhelpful line number.

Let's take an example of a test with an unmarked test helper. TestFoo(t) fails because testChdir(t, "/this/directory/does/not/exist") fails.

package b

import (
	"os"
	"testing"
)

func TestFoo(t *testing.T) {
	defer testChdir(t, "/this/directory/does/not/exist")()

	// ...
}

// https://speakerdeck.com/mitchellh/advanced-testing-with-go?slide=30
func testChdir(t *testing.T, dir string) func() {
	old, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if err := os.Chdir(dir); err != nil {
		t.Fatalf("err: %s", err) // b_test.go:22
	}

	return func() { os.Chdir(old) }
}

b_test.go:22 points to t.Fatalf("err: %s", err) inside of testChDir() which isn't so helpful to understand why the test failed.

$ go test
--- FAIL: TestFoo (0.00s)
    b_test.go:22: err: chdir /this/directory/does/not/exist: no such file or directory
FAIL
exit status 1
FAIL    github.com/ichiban/thelper/testdata/src/b       0.006s

By marking testChdir(), we can get a meaningful line number.

package b

import (
	"os"
	"testing"
)

func TestFoo(t *testing.T) {
	defer testChdir(t, "/this/directory/does/not/exist")() // b_test.go:9

	// ...
}

// https://speakerdeck.com/mitchellh/advanced-testing-with-go?slide=30
func testChdir(t *testing.T, dir string) func() {
	t.Helper()

	old, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if err := os.Chdir(dir); err != nil {
		t.Fatalf("err: %s", err)
	}

	return func() { os.Chdir(old) }
}

Now, b_test.go:9 points to defer testChdir(t, "/this/directory/does/not/exist")().

$ go test
--- FAIL: TestFoo (0.00s)
    b_test.go:9: err: chdir /this/directory/does/not/exist: no such file or directory
FAIL
exit status 1
FAIL    github.com/ichiban/thelper/testdata/src/b       0.006s

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Acknowledgments

This package is based on ikawaha's idea and advices.

About

Go static analyzer that reports where you forgot to call t.Helper().

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages