できない.dev

Go の go test がキャッシュで再実行されない

コード未変更で `go test` を再実行すると `(cached)` と表示されてテストが走らない場合、`-count=1` を付けるか `go clean -testcache` でキャッシュを破棄する。

#test#cache#count#ci

公開:

要約

go test ./... を 2 回目に流したら ok ... (cached) と出てテストが走らない、というのは Go のテストキャッシュが効いている状態です。
意図的に再実行するなら -count=1 を付けるのが公式推奨のイディオムです。

go test -count=1 ./...

キャッシュ自体を全部消したいなら次のコマンドを使います。

go clean -testcache

よくある原因

  1. 入力が変わっていない: Go は「テストバイナリ・対象パッケージのソース・環境変数・コマンドライン引数」が同じなら結果をキャッシュする。
    コードを 1 byte も変えずに再実行すれば当然 (cached) になる。
  2. 外部依存(DB・API・時刻)は Go の検出対象外: テスト関数の中で外部リソースを呼んでいても、Go から見ればソースが同じなので「同じ結果になる」とみなされる。
    フレーキーテスト調査時に困るポイント。
  3. CI で 2 回叩いた: パイプラインで go test を 2 段階に分けると、2 段目がキャッシュにヒットして実質スキップになる。

解決策

1. その場で再実行したいだけなら -count=1

go test -count=1 ./pkg/foo

-count は本来「テストを N 回ループ実行する」フラグですが、-count=1 を指定するとキャッシュをバイパスする副作用があるのが公式の推奨イディオムです(Testing flags)。

2. キャッシュ自体を消したい

go clean -testcache

$GOCACHE 配下のテスト結果を全削除します。
CI のキャッシュレイヤと組み合わせている場合はこちらが確実です。

3. CI ではキャッシュ無効化をデフォルトに

CI で go test を流すなら、最初から -count=1 を付けておくと「キャッシュで実行されない」事故を防げます。

- run: go test -count=1 ./...

go test-cpu / -tags / -race などの引数が変わると別キーとして扱うので、-race を付けたり外したりすると意図せず再実行される点も覚えておくと便利です。

この記事は役立ちましたか?