
Go で testing/fstest を使うと,ファイルシステムに依存したテストコードを書くときに実際のファイルシステムへの依存度を減らせる.テストコードを書こうとすると,テスト項目(バリエーション)ごとにファイルを用意する必要があるため,ファイルの管理が面倒になることもある.最近使う機会があって簡単にまとめておく📝
io/fs interface と testing/fstest.MapFS{}
testing/fstest の fstest.MapFS{} を使うと任意のファイルで構成されるファイルシステム(仕組みとしてはインメモリとドキュメントに書いてある)を作れる.そして,ファイルシステムを抽象化した io/fs.FS interface を満たすオブジェクトになっているため,ビジネスロジック側で fs.FS を受け取るように実装しておけば,テストコードでは fstest のオブジェクトを渡せる.
fs := fstest.MapFS{
"helloworld.md": {Data: []byte("helloworld")},
"helloworld2.md": {Data: []byte("helloworld2")},
"helloworld3.md": {Data: []byte("helloworld3")},
"helloworld4.md": {Data: []byte("helloworld4")},
"helloworld5.md": {Data: []byte("helloworld5")},
}
サンプルコード
以下のように main.go と main_test.go を書いてみた.
main.go
実装に特に意味はなくサンプルではあるけど,"files ディレクトリのファイル数を返す" というロジックを考える.ポイントはファイル数を返す countFiles() 関数の引数として fs.FS interface を受け取るようにしているところ❗️
package main import ( "fmt" "io/fs" "os" ) func countFiles(fsys fs.FS) (int, error) { files, err := fs.ReadDir(fsys, ".") if err != nil { return 0, err } return len(files), nil } func main() { count, err := countFiles(os.DirFS("files")) if err != nil { fmt.Println(err) } fmt.Println(count) }
main_test.go
テストコード側では testing/fstest.MapFS{} を使って,テスト項目ごとにファイルシステムを作っている(ファイルなし・1ファイル・2ファイル).もっともっとテスト項目が増えることを想像すると fstest を使うメリットが感じられると思う✌
package main import ( "testing" "testing/fstest" ) func TestCount(t *testing.T) { t.Run("File does not exist.", func(t *testing.T) { fs := fstest.MapFS{} want := 0 got, _ := countFiles(fs) assertCount(t, got, want) }) t.Run("One file exists.", func(t *testing.T) { fs := fstest.MapFS{ "helloworld.md": {Data: []byte("helloworld")}, } want := 1 got, _ := countFiles(fs) assertCount(t, got, want) }) t.Run("Two files exist.", func(t *testing.T) { fs := fstest.MapFS{ "helloworld.md": {Data: []byte("helloworld")}, "helloworld2.md": {Data: []byte("helloworld2")}, } want := 2 got, _ := countFiles(fs) assertCount(t, got, want) }) } func assertCount(t *testing.T, got, want int) { t.Helper() if got != want { t.Errorf("got %d, want %d", want, got) } }
まとめ
testing/fstest は便利だから覚えておこう〜❗️