23
package main

import (
    "flag"
    "fmt"
)

func main() {
    passArguments()
}

func passArguments() string {
    username := flag.String("user", "root", "Username for this server")
    flag.Parse()
    fmt.Printf("Your username is %q.", *username)

    usernameToString := *username
    return usernameToString
}

Passing an argument to the compiled code:

./args -user=bla

results in:

Your username is "bla"

the username that has been passed is displayed.


Aim: in order to prevent that the code needs to be build and run manually every time to test the code the aim is to write a test that is able to test the passing of arguments.


Attempt

Running the following test:

package main

import (
    "os"
    "testing"
)

func TestArgs(t *testing.T) {
    expected := "bla"
    os.Args = []string{"-user=bla"}

    actual := passArguments()

    if actual != expected {
        t.Errorf("Test failed, expected: '%s', got:  '%s'", expected, actual)
    }
}

results in:

Your username is "root".Your username is "root".--- FAIL: TestArgs (0.00s)
    args_test.go:15: Test failed, expected: 'bla', got:  'root'
FAIL
coverage: 87.5% of statements
FAIL    tool    0.008s

Problem

It looks like that the os.Args = []string{"-user=bla is not able to pass this argument to the function as the outcome is root instead of bla

030
  • 10,842
  • 12
  • 78
  • 123
  • 3
    Have you tried `os.Args = []string{"cmd", "-user=bla"}`? Remember the very first value in `os.Args` is a (path to) executable itself. – tomasz Nov 15 '15 at 18:48
  • @tomasz This works. Thank you. `args_test.go:16: Test failed, expected: 'bla', got: 'bla2'` – 030 Nov 15 '15 at 18:51
  • @tomasz Could you post your comment as an answer as it answers the question – 030 Nov 15 '15 at 18:56

2 Answers2

31

Per my comment, the very first value in os.Args is a (path to) executable itself, so os.Args = []string{"cmd", "-user=bla"} should fix your issue. You can take a look at flag test from the standard package where they're doing something similar.

Also, as os.Args is a "global variable", it might be a good idea to keep the state from before the test and restore it after. Similarly to the linked test:

oldArgs := os.Args
defer func() { os.Args = oldArgs }()

This might be useful where other tests are, for example, examining the real arguments passed when evoking go test.

tomasz
  • 12,574
  • 4
  • 43
  • 54
0

This is old enough but still searched out, while it seems out dated. Because Go 1.13 changed sth.

I find this change helpful, putting flag.*() in init() and flag.Parse() in Test*()

-args cannot take -<test-args>=<val> after it, but only <test-args>, otherwise the test-args will be taken as go test's command line parameter, instead of your Test*'s

A117
  • 499
  • 1
  • 5
  • 13