Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom command line flags in Go's unit tests

Have a moduled application. Have a bunch of tests that use a set of application modules, each test requires different set. Some modules are tuned through the command-line, e.g:

func init() {
    flag.StringVar(&this.customPath, "gamedir.custom", "", "Custom game resources directory")
}

But I cannot test this functionality. If I run

go test -test.v ./... -gamedir.custom=c:/resources

the runtime answers with

flag provided but not defined: -gamedir.custom

and fails the test.

What am I doing wrong with testing command-line args?

like image 787
snuk182 Avatar asked Dec 07 '14 13:12

snuk182


4 Answers

I think I got it what is wrong with flags in my case. With the following command

go test -test.v ./... -gamedir.custom=c:/resources

the compiler runs one or several tests on a workspace. In my particular case there are several tests, because ./... means find and create test executable for every _test.go file found. The test executable applies all the additional params unless one or some of them is ignored within it. Thus the test executables that do use param pass the test, all others fail. This may be overridden by running go test for each test.go separately, with appropriate set of params respectively.

like image 64
snuk182 Avatar answered Oct 17 '22 03:10

snuk182


The accepted answer, I found wasn't completely clear. In order to pass a parameter to a test (without an error) you must first consume that parameter using the flag. For the above example where gamedir.custom is a passed flag you must have this in your test file

var gamedir *string = flag.String("gamedir.custom", "", "Custom gamedir.")

Or add it to the TestMain

like image 23
notzippy Avatar answered Oct 17 '22 02:10

notzippy


You'll also get this message if you put your flag declarations inside of a test. Don't do this:

func TestThirdParty(t *testing.T) {
    foo := flag.String("foo", "", "the foobar bang")
    flag.Parse()
}

Instead use the init function:

var foo string
func init() {
    flag.StringVar(&foo, "foo", "", "the foo bar bang")
    flag.Parse()
}

func TestFoo() {
    // use foo as you see fit...
}
like image 13
Kevin Burke Avatar answered Oct 17 '22 04:10

Kevin Burke


Note that from Go 1.13, you'll get the following error if you use flag.Parse() in init()

flag provided but not defined: -test.timeout

To fix this, you have to use TestMain

func TestMain(m *testing.M) {
    flag.Parse()
    os.Exit(m.Run())
}

TestFoo(t *testing.T) {}
like image 4
pkk pmk Avatar answered Oct 17 '22 02:10

pkk pmk