testpackage はテストファイルが _test サフィックス付きの外部テストパッケージを使用しているかをチェックするツールです。
解決する問題
Go ではテストファイルを対象パッケージと同じパッケージ名で書くと、非公開(unexported)な関数やフィールドに直接アクセスできてしまいます。これにより内部実装に依存した壊れやすいテストになり、リファクタリングの妨げになります。
1 2 3 4 5 6 7 8 9 10 11
| package user
func TestCreateUser(t *testing.T) { u := User{name: "Alice", age: 30} err := u.validate() if err != nil { t.Fatal(err) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package user_test
import ( "testing" "myapp/internal/user" )
func TestCreateUser(t *testing.T) { u, err := user.NewUser("Alice", 30) if err != nil { t.Fatal(err) } if u.Name() != "Alice" { t.Errorf("got %q, want %q", u.Name(), "Alice") } }
|
設定
公式ドキュメント
1 2 3 4 5 6 7 8 9
| version: "2"
linters: enable: - testpackage settings: testpackage: skip-regexp: (export|internal)_test\.go
|
オプション
| オプション |
型 |
デフォルト |
説明 |
skip-regexp |
string |
(export|internal)_test\.go |
スキップするテストファイルの正規表現 |
allow-packages |
[]string |
[main] |
_test サフィックスなしでテストを許可するパッケージ名 |
サンプル
検出例
1 2 3 4 5 6 7 8 9 10 11
|
package user
import "testing"
func TestService(t *testing.T) { s := &service{repo: &mockRepo{}} _ = s }
|
修正例
1 2 3 4 5 6 7 8 9 10 11 12 13
| package user_test
import ( "testing" "myapp/internal/user" )
func TestService(t *testing.T) { repo := user.NewMockRepository() s := user.NewService(repo) _ = s }
|
export_test.go パターン
非公開関数をテストから使いたい場合は export_test.go でエクスポートする。デフォルトで skip-regexp により除外される。
1 2 3 4 5
| package user
var Validate = validate
|
1 2 3 4 5 6 7
| package user_test
func TestValidate(t *testing.T) { err := user.Validate("test@example.com") }
|
注意点
export_test.go と internal_test.go はデフォルトでスキップされる。これらのファイル名は Go の慣例で非公開シンボルのエクスポート用に使われる
main パッケージはデフォルトで許可される(main_test パッケージは実行できないため)
- 外部テストパッケージを使うことで、公開 API の設計品質を自然にテストできるようになる
参考リンク