Go 1.13 にアップデートするとテスト時に "flag provided but not defined" エラーが発生するケース
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)) } } }