{"id":13713767,"url":"https://github.com/ichiban/thelper","last_synced_at":"2026-01-14T15:38:43.264Z","repository":{"id":136953521,"uuid":"222910836","full_name":"ichiban/thelper","owner":"ichiban","description":"Go static analyzer that reports where you forgot to call t.Helper().","archived":false,"fork":false,"pushed_at":"2019-11-24T09:53:11.000Z","size":7,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T00:35:51.025Z","etag":null,"topics":["go","golang","static-analysis","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ichiban.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-20T10:24:12.000Z","updated_at":"2023-03-28T03:49:52.000Z","dependencies_parsed_at":"2024-05-13T00:54:32.689Z","dependency_job_id":"e135693c-550f-4425-b1c7-35d3db40b717","html_url":"https://github.com/ichiban/thelper","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ichiban/thelper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichiban%2Fthelper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichiban%2Fthelper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichiban%2Fthelper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichiban%2Fthelper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ichiban","download_url":"https://codeload.github.com/ichiban/thelper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichiban%2Fthelper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28424374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","static-analysis","testing"],"created_at":"2024-08-02T23:01:43.818Z","updated_at":"2026-01-14T15:38:43.258Z","avatar_url":"https://github.com/ichiban.png","language":"Go","funding_links":[],"categories":["Repositories"],"sub_categories":[],"readme":"# thelper\n\n[Go](https://golang.org/) [static analyzer](https://godoc.org/golang.org/x/tools/go/analysis) that reports where you forgot to call `t.Helper()`.\n\n## As a command\n\nFirst, install `thelper` command via `go get`.\n\n```shellsession\n$ go get github.com/ichiban/thelper/cmd/thelper\n```\n\nThen, run `thelper` command at your package directory.\n\n```shellsession\n$ thelper ./...\n/Users/ichiban/src/thelper/testdata/src/a/a_test.go:11:1: unmarked test helper: call t.Helper()\n/Users/ichiban/src/thelper/testdata/src/a/a_test.go:25:1: unmarked test helper: call s.Helper()\n```\n\n## As an `analysis.Analyzer`\n\nFirst, install the package via `go get`.\n\n```shellsession\n$ go get github.com/ichiban/thelper\n```\n\nThen, include `thelper.Analyzer` in your checker.\n\n```go\npackage main\n\nimport (\n\t\"golang.org/x/tools/go/analysis\"\n\t\"golang.org/x/tools/go/analysis/multichecker\"\n\t\"golang.org/x/tools/go/analysis/passes/nilfunc\"\n\t\"golang.org/x/tools/go/analysis/passes/printf\"\n\t\"golang.org/x/tools/go/analysis/passes/shift\"\n\n\t\"github.com/ichiban/thelper\"\n)\n\nfunc main() {\n\tmultichecker.Main(\n\t\t// other analyzers of your choice\n\t\tnilfunc.Analyzer,\n\t\tprintf.Analyzer,\n\t\tshift.Analyzer,\n\n\t\tthelper.Analyzer,\n\t)\n}\n```\n\n## What happens if I don't call `t.Helper()`?\n\n`go test` shows FAILs with an unhelpful line number.\n\nLet's take an example of a test with an unmarked test helper.\n`TestFoo(t)` fails because `testChdir(t, \"/this/directory/does/not/exist\")` fails.\n\n```go\npackage b\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestFoo(t *testing.T) {\n\tdefer testChdir(t, \"/this/directory/does/not/exist\")()\n\n\t// ...\n}\n\n// https://speakerdeck.com/mitchellh/advanced-testing-with-go?slide=30\nfunc testChdir(t *testing.T, dir string) func() {\n\told, err := os.Getwd()\n\tif err != nil {\n\t\tt.Fatalf(\"err: %s\", err)\n\t}\n\n\tif err := os.Chdir(dir); err != nil {\n\t\tt.Fatalf(\"err: %s\", err) // b_test.go:22\n\t}\n\n\treturn func() { os.Chdir(old) }\n}\n```\n\n`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.\n\n```shellsession\n$ go test\n--- FAIL: TestFoo (0.00s)\n    b_test.go:22: err: chdir /this/directory/does/not/exist: no such file or directory\nFAIL\nexit status 1\nFAIL    github.com/ichiban/thelper/testdata/src/b       0.006s\n```\n\nBy marking `testChdir()`, we can get a meaningful line number.\n\n```go\npackage b\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestFoo(t *testing.T) {\n\tdefer testChdir(t, \"/this/directory/does/not/exist\")() // b_test.go:9\n\n\t// ...\n}\n\n// https://speakerdeck.com/mitchellh/advanced-testing-with-go?slide=30\nfunc testChdir(t *testing.T, dir string) func() {\n\tt.Helper()\n\n\told, err := os.Getwd()\n\tif err != nil {\n\t\tt.Fatalf(\"err: %s\", err)\n\t}\n\n\tif err := os.Chdir(dir); err != nil {\n\t\tt.Fatalf(\"err: %s\", err)\n\t}\n\n\treturn func() { os.Chdir(old) }\n}\n```\n\nNow, `b_test.go:9` points to `defer testChdir(t, \"/this/directory/does/not/exist\")()`.\n\n```shellsession\n$ go test\n--- FAIL: TestFoo (0.00s)\n    b_test.go:9: err: chdir /this/directory/does/not/exist: no such file or directory\nFAIL\nexit status 1\nFAIL    github.com/ichiban/thelper/testdata/src/b       0.006s\n```\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n\n## Acknowledgments\n\nThis package is based on [ikawaha](https://github.com/ikawaha)'s idea and advices.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fichiban%2Fthelper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fichiban%2Fthelper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fichiban%2Fthelper/lists"}