testpackage

Table of Contents

  1. 解決する問題
  2. 設定
  3. オプション
  4. サンプル
    1. 検出例
    2. 修正例
    3. export_test.go パターン
  5. 注意点
  6. 参考リンク

testpackage はテストファイルが _test サフィックス付きの外部テストパッケージを使用しているかをチェックするツールです。

解決する問題

Go ではテストファイルを対象パッケージと同じパッケージ名で書くと、非公開(unexported)な関数やフィールドに直接アクセスできてしまいます。これにより内部実装に依存した壊れやすいテストになり、リファクタリングの妨げになります。

1
2
3
4
5
6
7
8
9
10
11
// Before: 内部パッケージでテスト(user パッケージ内)
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
// After: 外部テストパッケージを使用
package user_test

import (
"testing"
"myapp/internal/user"
)

func TestCreateUser(t *testing.T) {
// 公開 API のみを使ったテスト
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
# .golangci.yml 設定例
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
// testpackage が警告: package should be `user_test` instead of `user`

// user/service_test.go
package user // _test サフィックスがない

import "testing"

func TestService(t *testing.T) {
s := &service{repo: &mockRepo{}} // 非公開の struct に直接アクセス
_ = s
}

修正例

1
2
3
4
5
6
7
8
9
10
11
12
13
// user/service_test.go
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
// user/export_test.go
package user

// テスト用に非公開関数をエクスポート
var Validate = validate
1
2
3
4
5
6
7
// user/validate_test.go
package user_test

func TestValidate(t *testing.T) {
err := user.Validate("test@example.com")
// ...
}

注意点

  • export_test.gointernal_test.go はデフォルトでスキップされる。これらのファイル名は Go の慣例で非公開シンボルのエクスポート用に使われる
  • main パッケージはデフォルトで許可される(main_test パッケージは実行できないため)
  • 外部テストパッケージを使うことで、公開 API の設計品質を自然にテストできるようになる

参考リンク