元エントリは↓で、これが全てです。
— k1LoW (@k1LoW) 2023年8月26日
Goでツールではなくライブラリ(パッケージ)を作っているとき、テストにしか使わないパッケージがgo.modに入って依存関係ができてしまうのが、いつも気になっていました。
ただ、「まあ別にいいかな」と思っていたのですが、ちょうど標準パッケージだけで機能が実現できるパッケージができたので、どうしてもgo.modを綺麗にしたくなりました。
そして、えいっと調べてみたらすぐに解決方法が見つかったのでした。
テストでしか使わないパッケージをgo.modに含めない方法
方法は次の通りです*1。
- テスト用に go_test.mod ファイルを用意して
-modfile
オプションを使って go_test.mod ファイルを指定してgo test
を実行する - (例えば)go.modの更新に
go mod tidy
を使わない
テスト用に go_test.mod ファイルを用意して -modfile
オプションを使って go_test.mod ファイルを指定して go test
を実行する
-modfile
でgo.modを指定できるので(知らなかった!)、テスト用にgo_test.modファイルを指定するようにすることでパッケージとしての依存関係とテスト実行時の依存関係を別に管理します。
(例えば)go.modの更新に go mod tidy
を使わない
go mod tidy works by loading all of the packages in the main module and all of the packages they import, recursively.
とのことで、これにはテストコードも含まれます。
なので、 go mod tidy
をそのまま使用することをやめるか、
Note that go mod tidy will not consider packages in the main module in directories named testdata or with names that start with . or _ unless those packages are explicitly imported by other packages.
とのことなので、テストコードを testdata ディレクトリ以下に押し込んでしまえば、テストでしか使わないパッケージが go.mod に入ることを回避できそうです。
ただ、 go mod tidy
が使えないのは面倒...
具体的にどうしているか
https://github.com/k1LoW/rp/blob/aa26b46a7d17cdeb16370c1b704ee741c5e7b5b4/Makefile#L8-L10
$ cp go.mod testdata/go_test.mod $ go mod tidy -modfile=testdata/go_test.mod $ go test ./... -modfile=testdata/go_test.mod -coverprofile=coverage.out -covermode=count
のような感じで go_test.mod を生成してテストを実行しています。
もっといい方法がありそう
「私はこうやって解決しているよ」というのがあれば是非教えてください!
*1:エントリ公開当初「テストコードを別パッケージにする」と書いていましたが特に必要ありませんでした