💨

Go言語で flag.Arg を使ったコードのテスト

2024/10/04に公開

概要

  • Go言語の flag パッケージの Arg を使ったコードでテストをする

背景

flag パッケージのうち,フラグを指定しているコードのテストは見つかったものの,
(Arg を使った)実行時の引数を指定しているコードのテストが見つからなかったから.

対象読者

  • Go言語を使っている
  • テストを書いている
  • flagパッケージを使っている
  • flag.Arg(0) などの引数を使ったコードのテストを書きたい

環境

今回の環境は次である.

$ go version
go version go1.23.1 linux/amd64

本論

フラグ: $main -flag="hoge"
引数: $main "hoge"

フラグを指定

まず,前提知識的にフラグを使ったテストコードについて述べる.
go テスト フラグ などで Google 検索すれば出てくる情報である.*1
flag.CommandLine.Set を使って,フラグをプログラム内で設定する方法となる.

for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {

        // $main -flag="hoge" と同じ
        flag.CommandLine.Set("flag", "hoge")

        if got := hoge(); got != tt.want {
            t.Errorf("hoge() = %v, want %v", got, tt.want)
        }
    })
}

引数を指定

今回やりたかった,実行時の引数を指定したテストコードについて述べる.
os.Args を直接設定することで、実行時の引数をエミュレートする方法となる.

for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {

        // $main "hoge" と同じ
		os.Args = "hoge"

        if got := hoge(); got != tt.want {
            t.Errorf("hoge() = %v, want %v", got, tt.want)
        }
	})
}

コード全体の例

package flags

import (
	"os"
	"testing"
)

func TestParse(t *testing.T) {
	tests := []struct {
		name string
		args []string
		want string
	}{
		{
			name: "引数が1つの場合",

            // 設定しない場合,第一引数はプログラム名が入る.
            // 上書きしない方法はわからない…
			args: []string{"main", "hello"},

			want: "hello",
		},
		{
			name: "引数が複数の場合",
			args: []string{"main", "hello", "world"},
			want: "hello",
		},
		{
			name: "引数がない場合",
			args: []string{"main"},
			want: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			os.Args = tt.args
			if got := Parse(); got != tt.want {
				t.Errorf("hoge() = %v, want %v", got, tt.want)
			}
		})
	}
}

参考

1

GitHubで編集を提案

Discussion