テスト用パッケージをgo.modから除く(非推奨)

cronplanにそれなりにスターがついたので、go.modからテスト用パッケージを除いてみた。

以下、cronplanをv1.10.1→v1.10.4に変更したときのgo.sumの差分。

$ go get github.com/winebarrel/cronplan@v1.10.1
$ go mod tidy
$ cp go.sum go.sum.bak

$ go get github.com/winebarrel/cronplan@v1.10.4
$ go mod tidy
$ diff -u go.sum.bak go.sum
--- go.sum.bak   2024-11-22 23:06:12
+++ go.sum    2024-11-22 23:11:45
@@ -4,15 +4,7 @@
 github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c=
 github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
 github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/winebarrel/cronplan v1.10.1 h1:sTnmKWpGjXr3tDpgSSTCohltaimpBNXW/LgFf0SEMwo=
-github.com/winebarrel/cronplan v1.10.1/go.mod h1:FXpmoZVzj9eZoyHe1lpUezcFL3Tk6p5OBSovWeHq4qY=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+github.com/winebarrel/cronplan v1.10.4 h1:lpDvd+gihqGEi7aYcvmJ1nyFVCXDULMk8XPvUQtcPyQ=
+github.com/winebarrel/cronplan v1.10.4/go.mod h1:ZGEHrRZU3YNI22nDLTr9obcRMX3uBYPektCQoCmFmaY=

testify関係のパッケージがなくなっていることがわかる。

経緯

cmd/以下のCLIの依存がgo.modに入るのがいやだったので、ライブラリと関係ないものをgo.modから除外してみた(…のだが、その後調べたらcmd/以下で使われているパッケージは go get github.com/winebarrel/cronplan をしても依存に追加されなかった)

そのついでで、テスト用のパッケージもgo.modに含まれないようになった。

方法

サブディレクトリにgo.modがあると、ルートディレクトリのgo.modにはサブディレクトリのパッケージが含まれなくなる。 なのでテスト用のソースコードはtestディレクトリに置くようにして、そこにgo.modをおいた。

ただし、そのままだとライブラリのパッケージを直接参照できないので、replaceを使って上位ディレクトリのパッケージを参照するようにした。

具体的にはtest/go.modがこんな感じ:

module github.com/winebarrel/cronplan/test

go 1.21

toolchain go1.21.1

// replaceで上位ディレクトリのパッケージを参照する
replace github.com/winebarrel/cronplan => ../

require (
    github.com/stretchr/testify v1.9.0
    // バージョン番号はダミー値
    github.com/winebarrel/cronplan v0.0.0-00010101000000-000000000000
)

require (
    github.com/alecthomas/participle/v2 v2.1.1 // indirect
    github.com/davecgh/go-spew v1.1.1 // indirect
    github.com/pmezard/go-difflib v1.0.0 // indirect
    gopkg.in/yaml.v3 v3.0.1 // indirect
)

これで go get github.com/winebarrel/cronplan してもtestifyが依存に追加されなくなる。

非推奨

以下の点であまり推奨できるやり方ではないと思っている。

  • ディレクトリ構成が非標準的になる
  • replaceがhacky
  • テストでしか使われているパッケージがダウンロードされても実害はないような気がする
    • _test.goであればビルドから除外されるし、使ってないものはリンクされないのではないだろうか?
    • dependabotが少しうっとうしくなるかもしれない

先行事例

k1low.hatenablog.com

go mod tidyを使いたかったので、このやり方にはしなかった。

その他

増えたgo.modを再帰的に探索してほしかったので、cronplanの依存パッケージのバージョンアップをdependabotからrenovateに変えることになった。