Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process command line arguments in go test

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:

  1. not all tests are unit tests
  2. it is very functional not to rely on "ENV" variables and actually pass the stuff as arguments in command line,

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.

like image 615
Ali Avatar asked Jan 25 '14 13:01

Ali


People also ask

How do you implement command-line arguments in go?

Command-line arguments are a way to provide the parameters or arguments to the main function of a program. Similarly, In Go, we use this technique to pass the arguments at the run time of a program. In Golang, we have a package called as os package that contains an array called as “Args”.

How do you access command-line arguments in Golang?

In Go, you can access the raw command-line arguments using the os. Args variable. It is a slice and it holds all the command-line arguments starting with the program name.

How do I run a test from command-line?

To run your tests in this mode, run go test in your project's root directory. In the package list mode, go test compiles and tests each package listed as arguments to the command. If a package test passes, go test prints only the final 'ok' summary line. If a package test fails, go test prints the complete test output.

What does go test command do?

The go test command executes test functions (whose names begin with Test ) in test files (whose names end with _test.go). You can add the -v flag to get verbose output that lists all of the tests and their results. The tests should pass.


3 Answers

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
    // ...
}
like image 127
Samuel A. Falvo II Avatar answered Oct 27 '22 13:10

Samuel A. Falvo II


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)
    ...
}
like image 29
pajato0 Avatar answered Oct 27 '22 12:10

pajato0


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.
}
like image 9
Mark Farnan Avatar answered Oct 27 '22 14:10

Mark Farnan