Go でテストを実行する際は動的に生成された main
関数がエントリポイントとなっています。
Go 1.13 からはテスト実行時のテストフラグ (-v
や -coverprofile
など) の登録がこの生成された main 内で行われるようになったため、 main
より先に実行される init
内でフラグの登録を行っているテストではフラグのパースがうまく動かず、テストが落ちるようになります。
たとえば、自分が開発している Evans では golden files testing のために --update
フラグを e2e
パッケージで用意し、これが有効になっている場合のみ golden files を更新するような設定になっていました。
var ( update = flag.Bool("update", false, "update goldens") ) func init() { flag.Parse() if *update { os.RemoveAll(filepath.Join("testdata", "fixtures")) if err := os.MkdirAll(filepath.Join("testdata", "fixtures"), 0755); err != nil { panic(fmt.Sprintf("failed to create fixture dirs: %s", err)) } } }
$ go test -v flag provided but not defined: -test.v Usage of /var/folders/p8/yjvb_xcn54d3dsfjz76rywvh0000gn/T/go-build261037663/b001/e2e.test: -update update goldens exit status 2 FAIL github.com/ktr0731/evans/e2e 0.018s
これを回避するためには Go 1.13 で新たに追加された testing.Init()
を init
内で呼びます。
これはテストフラグを明示的に登録してくれる関数で、これをフラグのパース前に呼ぶことで正常にパースすることができるようになります。
var ( update = flag.Bool("update", false, "update goldens") ) func init() { testing.Init() flag.Parse() if *update { os.RemoveAll(filepath.Join("testdata", "fixtures")) if err := os.MkdirAll(filepath.Join("testdata", "fixtures"), 0755); err != nil { panic(fmt.Sprintf("failed to create fixture dirs: %s", err)) } } }