Reputation: 19682
Is there a way to get the command line arguments in go "tests",
When you call go test
obviously your main
is not run, so is there a way to process command line arguments,
One way would be to use the flags
packages and check for the command line arguments in each test or function being tested, but that is not ideal for that you need to do this in lots and lots of places, unlike the way you to it just in main
when you run the application.
One may think it is a wrong thing to do, and that it is against purity of unit-tests:
For the record I ended up putting an init()
function in one of my _test
files, and set the variable that is set through flags when the main is called this way.
Upvotes: 39
Views: 49686
Reputation: 10290
While I was working through some of the issues with using init()
to parse flags during my test setup, I found jbowen's post on this subject which provides a simpler way of accessing the incoming flags in a test run, based on the fact that flag.Parse()
is already executed by go test
.
var stringArg = flag.String("my-arg", "default", "value for my-arg")
This needs to be defined in the package scope so that the flag module picks it up before parsing. Otherwise it provides you easy access to an additionally defined flag and I imagine it could be defined in a reusable test fixture package.
Upvotes: 1
Reputation: 151
You can directly test main function and pass arguments.
Simple example showing a flag, and a pair of positional arguments
Note: Do NOT call it 'TestMain' that has a special meaning to the testing framework as of Go 1.8.
package main
import (
"os"
"testing"
)
func TestMainFunc(t *testing.T) {
os.Args = append(os.Args, "--addr=http://b.com:566/something.avsc")
os.Args = append(os.Args, "Get")
os.Args = append(os.Args, `./some/resource/fred`)
main()
// Test results here, and decide pass/fail.
}
Upvotes: 15
Reputation: 69
os.Args[1] = "-conf=my.conf"
flag.Parse()
Notice that the config file name is hard-coded.
Upvotes: 6
Reputation: 900
Environmental configs are best kept in environment variables, in my experience. You can rely on global variables like so:
var envSetting = os.Getenv("TEST_ENV")
Alternatively, if using flags is a requirement, you could place your initialization code inside a function called init().
func init() {
flags.Parse()
myEnv = *envFlag
// ...
}
Upvotes: 18
Reputation: 3676
An alternative approach is to make main()
be a stub that merely calls into another function after arguments are processed by flag.Parse()
, for example:
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help for flagname")
}
func main() {
flag.Parse()
submain(flag.Args)
}
func submain(args []string) {
...
}
Then in your tests, flag variables can be set and arguments established before calling submain(...)
simulating the command line establishment of flags and arguments. This approach can be used to maximize test coverage without actually using a command line. For example, in main_test.go, you might write:
func TestSomething(t *testing.T) {
flagvar = 23
args := []string{"a", "b", "c"}
submain(args)
...
}
Upvotes: 9