Upgrade to Pro — share decks privately, control downloads, hide ads and more …

testdata ディレクトリを活用しよう!

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for uji uji
December 01, 2025
330

testdata ディレクトリを活用しよう!

Avatar for uji

uji

December 01, 2025
Tweet

More Decks by uji

Transcript

  1. © NOT A HOTEL, Inc. 自己紹介 uji @uji_rb 神戸市在住 NOT

    A HOTEL 所属 Gopher 7年生 KOBE.go, Kyoto.go 運営 Kyoto.go KOBE.go
  2. © NOT A HOTEL, Inc. © NOT A HOTEL, Inc.

    testdata 活用 Tips を3つ紹介 4
  3. © NOT A HOTEL, Inc. testdata とは? • テストに利用する補助データを 置いておくことができるディレクトリ

    • Go ツールはビルドなどからは testdata と命名された ディレクトリは無視されるので安全(doc) ◦ 中に .go ファイルがあってもビルド対象にならない
  4. © NOT A HOTEL, Inc. 何が嬉しい? • 入出力データや状態が複雑になるテストの 可読性や保守性を上げられる •

    Table Driven Test でも可読性や保守性を 高くしきれない場面で有効。 テストケースと検証ロジックの分離度がさらに上がる
  5. © NOT A HOTEL, Inc. 基本的な使い方 • 任意の場所に testdata ディレクトリを作成

    • テストで利用するファイルを用意 • 標準 pkg でテストコードからファイルを読み取り ◦ os.Open(“testdata/xxx.png”) や embed など • src/image/testdata など golang/go でも実例がたくさん
  6. © NOT A HOTEL, Inc. © NOT A HOTEL, Inc.

    Tips 1 Golden Test に利用する 8
  7. © NOT A HOTEL, Inc. Golden Test とは? • テスト対象の出力結果を事前に保存された

    “Golden” ファイル と比較するテスト手法 • コードの変更した際、意図しない変更や 回帰がないかを検証するために特に有用 • “Golden” は、 「黄金の価値がある」「非常に信頼性の高い」という意味合いが由来
  8. © NOT A HOTEL, Inc. Golden Test の書き方 • Golden

    ファイルを testdata に格納し読み書き • flag パッケージを活用することで、 Golden ファイルの生成機構も簡単に用意できる
  9. © NOT A HOTEL, Inc. golang/go/src/go/doc/doc_test.go の例 var update =

    flag.Bool("update", false, "update golden (.out) files") ... func test(t *testing.T, mode Mode) { ... for _, pkg := range pkgs { t.Run(pkg.Name, func(t *testing.T) { ... // Golden ファイルのupdate golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode)) if *update { err := os.WriteFile(golden, got, 0644) if err != nil { t.Fatal(err) } } // Golden ファイルの取得 want, err := os.ReadFile(golden) if err != nil { t.Fatal(err) } // 検証 ...
  10. © NOT A HOTEL, Inc. golang/go/src/go/doc/doc_test.go の例 var update =

    flag.Bool("update", false, "update golden (.out) files") ... func test(t *testing.T, mode Mode) { ... for _, pkg := range pkgs { t.Run(pkg.Name, func(t *testing.T) { ... // Golden ファイルのupdate golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode)) if *update { err := os.WriteFile(golden, got, 0644) if err != nil { t.Fatal(err) } } // Golden ファイルの取得 want, err := os.ReadFile(golden) if err != nil { t.Fatal(err) } // 検証 ... flag パッケージで変数を宣言
  11. © NOT A HOTEL, Inc. golang/go/src/go/doc/doc_test.go の例 var update =

    flag.Bool("update", false, "update golden (.out) files") ... func test(t *testing.T, mode Mode) { ... for _, pkg := range pkgs { t.Run(pkg.Name, func(t *testing.T) { ... // Golden ファイルのupdate golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode)) if *update { err := os.WriteFile(golden, got, 0644) if err != nil { t.Fatal(err) } } // Golden ファイルの取得 want, err := os.ReadFile(golden) if err != nil { t.Fatal(err) } // 検証 ... flag 変数で条件分岐
  12. © NOT A HOTEL, Inc. • go test で生成されるテストバイナリは、 内部で

    flag.Parse() を呼び出している (code) • フラグ変数をグローバル変数として定義すれば、 go test -update などでテストに値を渡すことができる
  13. © NOT A HOTEL, Inc. © NOT A HOTEL, Inc.

    Tips 2 txtar 形式を活用する 15
  14. © NOT A HOTEL, Inc. • Go 言語のエコシステム内で利用される、 アーカイブ形式の一つ •

    複数のファイルの内容を単一のテキストファイルに まとめて表現するための形式 txtar とは?
  15. © NOT A HOTEL, Inc. • golang.org/x/tools/txtar でライブラリが サポートされている ◦

    例えば txtar.Parse() で簡単に複数ファイルを取得可能 • 活用例 ◦ テストの入力・出力をセットで扱う ◦ ファイルシステムの状態を表現 txtar の活用方法
  16. © NOT A HOTEL, Inc. © NOT A HOTEL, Inc.

    Tips 3 script-based test で利用する 20
  17. © NOT A HOTEL, Inc. • テストケースをスクリプト (手順と期待結果を記述した文書)で記述するテスト • Go公式の

    cmd/go のテストでもヘビーに利用 ◦ Russ Cox 氏により、 internal package で独自の スクリプト言語が実装されている(README) • testdata でテストスクリプトを管理している script-based test とは?
  18. © NOT A HOTEL, Inc. src/cmd/go/testdata/script/test_status.txt の例 env GO111MODULE=off !

    go test x y stdout ^FAIL\s+x stdout ^ok\s+y stdout (?-m)FAIL\n$ -- x/x_test.go -- package x import "testing" func TestNothingJustFail(t *testing.T) { t.Fail() } -- y/y_test.go -- package y このファイルを scripttest.Run() に渡すと テストが動作 src/cmd/go/script_test.go#L40
  19. © NOT A HOTEL, Inc. • Go で使われているスクリプト言語を利用するためのライ ブラリは github.com/rsc/script

    にて Russ Cox 氏が公開 • 別の記述スタイルが欲しければ自作するのもアリ…? ◦ 多様なパターンをテストしたい場合はコストに見合う価値はあるかも 同じように script-based test を書くには
  20. © NOT A HOTEL, Inc. 他にも testdata 活用 Tips があれば是非

    #go_findy で教えてください! 参考文献 • research!rsc: Go Testing By Example https://research.swtch.com/testing • Bitfield Consulting: Flipping the script: a smarter way to test Go binaries https://bitfieldconsulting.com/posts/test-scripts