jessevdk / go-flags

go command line option parser
http://godoc.org/github.com/jessevdk/go-flags
BSD 3-Clause "New" or "Revised" License
2.59k stars 308 forks source link

Can flags be used to parse command line arguments from 'go test' ? #378

Closed a-dot closed 2 years ago

a-dot commented 2 years ago

I tried different combinations for parsing command line arguments when using go test but could not get it to work.

Option 1 - flags.Parse from a Test

type options struct {
    Foo     time.Duration `short:"f" long:"foo"`
}
var opts options

func TestSomeTest(t *testing.T) {
    _, _ = flags.Parse(&opts)
}

When running go test -v ./... -args -f 1s I get

flag provided but not defined: -f
Usage of /var/folders/x3/2xrtbbmn5h3_k7m7091thp940000gn/T/go-build1296679627/b001/test.test:
  -test.bench regexp
        run only benchmarks matching regexp
  -test.benchmem
[...]

Option 2 - flags.Parse from TestMain

type options struct {
    Foo     time.Duration `short:"f" long:"foo"`
}
var opts options

func TestMain(m *testing.M) {
    _, _ = flags.Parse(&opts)

    os.Exit(m.Run())
}

When running go test -v ./... -args -f 1s I get

unknown flag `t'
flag provided but not defined: -f
Usage of /var/folders/x3/2xrtbbmn5h3_k7m7091thp940000gn/T/go-build1659405760/b001/test.test:
  -test.bench regexp
        run only benchmarks matching regexp
  -test.benchmem
[...]

Option 3 - flags.Parse from init

ype options struct {
    Foo     time.Duration `short:"f" long:"foo"`
}
var opts options

func init() {
    _, _ = flags.Parse(&opts)
}

When running go test -v ./... -args -f 1s I get

unknown flag `t'
flag provided but not defined: -f
Usage of /var/folders/x3/2xrtbbmn5h3_k7m7091thp940000gn/T/go-build606016704/b001/test.test:
  -test.bench regexp
        run only benchmarks matching regexp
  -test.benchmem
[...]

How are we supposed to use flags for command line arguments for tests? Thanks!

a-dot commented 2 years ago

The couple ways I found to do this is to use flags.ParseArgs() and supply it with a modified slice of arguments. I had to remove the -test. arguments.

The cleaner way to do this I found is to create a new parser and use the IgnoreUnknown option. Use the returned args to modify os.Args to do something like this os.Args = append([]string{os.Args[0]}, args...)

AlexPykavy commented 2 years ago

I've faced the same issue and could overcome it by using --, like:

go test -v ./... -- -f 1s

In my case, the problem was also caused by the parallel tests execution. As it turns out, go runs tests in parallel when ./... pattern passed (see https://engineering.mercari.com/en/blog/entry/20220408-how_to_use_t_parallel/.). And it means that each package (subfolder) should handle these additional arguments. Using -- helps to consider these following arguments as positional and thereby not be handled by go test.