14
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

こんにちわ
ゴリラです

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したりしているので、
シンプルだけど勉強になりそうなので、興味ある方はソースを読んでみてください。

14
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?