tenv

Table of Contents

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

tenv はテストコード内で os.Setenv の代わりに t.Setenv(Go 1.17+)を使うよう促すツールです。

解決する問題

テスト内で os.Setenv を使って環境変数をセットすると、テスト終了後に手動で元に戻す必要があります。戻し忘れると他のテストに影響し、テストの実行順序によって結果が変わる不安定なテストになります。t.Setenv はテスト終了時に自動でクリーンアップしてくれます。

1
2
3
4
5
6
7
8
9
// Before: os.Setenv は手動で元に戻す必要がある
func TestProcessConfig(t *testing.T) {
original := os.Getenv("DATABASE_URL")
os.Setenv("DATABASE_URL", "postgres://localhost/test")
defer os.Setenv("DATABASE_URL", original) // 忘れると他のテストに影響

result := processConfig()
// ...
}
1
2
3
4
5
6
7
8
// After: t.Setenv は自動でクリーンアップされる
func TestProcessConfig(t *testing.T) {
t.Setenv("DATABASE_URL", "postgres://localhost/test")
// テスト終了時に自動で元の値に戻る

result := processConfig()
// ...
}

設定

公式ドキュメント

1
2
3
4
5
6
7
8
9
# .golangci.yml
version: "2"

linters:
enable:
- tenv
settings:
tenv:
all: true

オプション

オプション デフォルト 説明
all bool false true にすると _test.go ファイル全体をチェック(ヘルパー関数内の os.Setenv も検出)

デフォルトでは *testing.T*testing.Btesting.TB を引数に取る関数内のみチェックされます。all: true にすると、テストファイル内のすべての関数(ヘルパー関数を含む)がチェック対象になります。

サンプル

検出例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// tenv が警告するパターン

// 1. テスト関数内の os.Setenv
func TestFetchData(t *testing.T) {
os.Setenv("API_KEY", "test-key") // os.Setenv() can be replaced by `t.Setenv()` in TestFetchData
// ...
}

// 2. ベンチマーク内の os.Setenv
func BenchmarkProcess(b *testing.B) {
os.Setenv("MODE", "benchmark") // os.Setenv() can be replaced by `b.Setenv()` in BenchmarkProcess
// ...
}

// 3. all: true の場合、ヘルパー関数も対象
func setupEnv() {
os.Setenv("GO_ENV", "test") // os.Setenv() can be replaced by `testing.Setenv()`
}

修正例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1. テスト関数内
func TestFetchData(t *testing.T) {
t.Setenv("API_KEY", "test-key") // テスト終了時に自動で元に戻る
// ...
}

// 2. ベンチマーク内
func BenchmarkProcess(b *testing.B) {
b.Setenv("MODE", "benchmark")
// ...
}

// 3. ヘルパー関数は t を受け取るように変更
func setupEnv(t *testing.T) {
t.Helper()
t.Setenv("GO_ENV", "test")
}

注意点

  • Go 1.17 以降が必要(t.Setenv はこのバージョンで追加された)
  • t.Setenv は内部で t.Parallel() との併用を禁止している。並列テストで環境変数を使う場合は別の方法(構造体のフィールドで渡すなど)を検討する
  • all: true を有効にすると、テストのヘルパー関数にも *testing.T を渡す設計に自然と誘導される

参考リンク