How to run multiple tests that use flag.Var() without "flag redefined" panic

3,047 views
Skip to first unread message

sheale...@gmail.com

unread,
Jan 8, 2015, 6:14:46 PM1/8/15
to golan...@googlegroups.com
The code I am testing uses command line flags:
 
// config.go 
package config
import "flag"
func CreateConfig() (ConfigStruct, error) {
    configPath := flag.String("config", defaultConfig, "config file path")
   ...
}

The thing is, if I run multiple tests of this code, I get a flag-redefined error:

// config_test.go
package config_test
import "my/path/config"
func TestCreateConfig() {
    config.CreateConfig()
    ...
}

E.g.
/tmp/go-build887413297/mypath/config/_test/config.test flag redefined: custom_config
/usr/local/go/src/runtime/panic.go:387

I believe this is because I only import the flag package once, so any call to flag.Var() looks at the same f.formal map.

Being only able to run one test is almost like not being able to run any at all, so I'm eager to hear how I can work around this or where my (misunderstanding is leading me astray.

Thanks

Ian Lance Taylor

unread,
Jan 8, 2015, 7:15:44 PM1/8/15
to sheale...@gmail.com, golang-nuts
On Thu, Jan 8, 2015 at 3:14 PM, <sheale...@gmail.com> wrote:
>
> The code I am testing uses command line flags:
>
>>
>> // config.go
>>
>> package config
>>
>> import "flag"
>>
>> func CreateConfig() (ConfigStruct, error) {
>> configPath := flag.String("config", defaultConfig, "config file path")
>> ...
>> }

Is there any reason to only create the flag in CreateConfig? Why not
use a global variable?

Ian

sheale...@gmail.com

unread,
Jan 8, 2015, 7:39:18 PM1/8/15
to golan...@googlegroups.com, sheale...@gmail.com
1. I created the flag in the CreateConfig() function to keep the whole config getting/maintaining cordoned off in the config package so I can inject it around (nice for testing, etc).

2. I also realized where my misunderstanding lay. I solved my problem by giving the config package an init() function that calls flag.String(), and then waiting to call flag.Parse() in config.CreateConfig():

// config.go
package config
import "flag"

val configPath
*string
func init
() {
 configPath
:= flag.String("config", "", "config file path")
}
func
CreateConfig() (ConfigStruct, error) {
 flag
.Parse()
 
use(*configPath)
 
...
}


Then I have no problems calling CreateConfig multiple times, as I wanted to.


// config_test.go
package config_test
import "my/path/config"
func
TestCreateConfig() {
    config
.CreateConfig()
   
...
}

Thanks!

Matt Harden

unread,
Jan 10, 2015, 9:18:34 AM1/10/15
to sheale...@gmail.com, golan...@googlegroups.com
You could also create a new FlagSet in CreateConfig flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError) and use that instead of the global flagset flag.CommandLine.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages