Posted at

Goでテスト時にflag引数に任意の値を渡す

こんにちわ

ゴリラです

Goでテストを書く時、コマンドライン引数に任意の値を渡したい事があったので、

そのやり方をメモとして残しておきます。


flag引数

Goでは -arg value という感じで、flagパッケージ引数を定義することができます。

var (

name = flag.String("name", "gorilla", "your name")
age = flag.Int("age", 10, "your age")
isHuman = flag.Bool("isHuman", false, "are your human?")
)

func echo() string {
return fmt.Sprintf("your status: name:%s, age:%d, isHuman:%v", *name, *age, *isHuman)
}


やり方

この引数の値をテスト時に任意の変更して、分岐を網羅したいときがあります。

そういった場合は、flagパッケージで用意されている flag.CommandLine.Set 関数を使うことで、

任意の値をセットすることができます。

func TestEcho(t *testing.T) {

tests := []struct {
name string
age string
isHuman string
want string
}{
{name: "gorilla", age: "26", isHuman: "false", want: "your status: name:gorilla, age:26, isHuman:false"},
{name: "dog", age: "10", isHuman: "false", want: "your status: name:dog, age:10, isHuman:false"},
{name: "bob", age: "30", isHuman: "true", want: "your status: name:bob, age:30, isHuman:true"},
}

for _, test := range tests {
flag.CommandLine.Set("name", test.name)
flag.CommandLine.Set("age", test.age)
flag.CommandLine.Set("isHuman", test.isHuman)

got := echo()
if test.want != got {
t.Fatalf("want %s, but got %s", test.want, got)
}
}
}

CommandLine.Set の引数は keyvalue があり、ともにstringですが、

value は内部でよしなに型変換してくれるので、intやboolも全てはstringで渡す必要があります。


まとめ

flag引数とそれ以外の引数をまとめて持っているのが flag.FlagSet という構造体です。

type FlagSet struct {

// Usage is the function called when an error occurs while parsing flags.
// The field is a function (not a method) that may be changed to point to
// a custom error handler. What happens after Usage is called depends
// on the ErrorHandling setting; for the command line, this defaults
// to ExitOnError, which exits the program after calling Usage.
Usage func()

name string
parsed bool
actual map[string]*Flag
formal map[string]*Flag
args []string // arguments after flags
errorHandling ErrorHandling
output io.Writer // nil means stderr; use out() accessor
}

args がflag引数以外の引数が入り、 formal がflag引数が入っています。

深くは読んでいないのですが、interfaceを使用して、valueをparseしたりしているので、

シンプルだけど勉強になりそうなので、興味ある方はソースを読んでみてください。