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
は便利だから覚えておこう〜❗️