Slide 1

Slide 1 text

t *testing.T は どこからやってくるの? おーたかこーたろー / @otakakot 2026.04.22 Go Connect #12 The Go gopher was designed by Renée French.

Slide 2

Slide 2 text

ある日... #goconnect

Slide 3

Slide 3 text

データベースを使ったテストを 実装していたときの話 #goconnect

Slide 4

Slide 4 text

#goconnect

Slide 5

Slide 5 text

context canceled が発生して クリーンアップ処理に失敗 #goconnect

Slide 6

Slide 6 text

pgx パッケージを確認 #goconnect

Slide 7

Slide 7 text

t.Context() がキャンセルされている #goconnect

Slide 8

Slide 8 text

Bad! Good! #goconnect

Slide 9

Slide 9 text

t.Cleanup() では t.Context() は キャンセル済み! #goconnect

Slide 10

Slide 10 text

ところで... #goconnect

Slide 11

Slide 11 text

この t *testing.Tはどこからくるのか #goconnect

Slide 12

Slide 12 text

そもそも Go は main パッケージの main 関数が実行されるんでしょ #goconnect

Slide 13

Slide 13 text

#goconnect

Slide 14

Slide 14 text

なぜこのコードは動く ... ??? #goconnect

Slide 15

Slide 15 text

TextXxx は黒魔術...??? #goconnect

Slide 16

Slide 16 text

go test が動く仕組み #goconnect

Slide 17

Slide 17 text

おさらい #goconnect

Slide 18

Slide 18 text

#goconnect How to Write Go Code #Testing go test コマンドと testing パッケージ _test.go で終わるファイル func TestXXX(t *testing.T) 関数 https://go.dev/doc/code#Testing

Slide 19

Slide 19 text

#goconnect https://go.dev/doc/code#Testing

Slide 20

Slide 20 text

結論 #goconnect

Slide 21

Slide 21 text

#goconnect go test は ... テスト関数を呼び出す Go コード (main関数)を自動生成し コンパイルして実行している!

Slide 22

Slide 22 text

全体像 go test コマンド実行 ファイルの分類・関数の収集 _testmain.go の生成 ビルド 実行 #goconnect

Slide 23

Slide 23 text

注釈 ステップ数はおーたかによる解釈 #goconnect

Slide 24

Slide 24 text

サンプルコード #goconnect

Slide 25

Slide 25 text

go version Go 1.26.2 #goconnect

Slide 26

Slide 26 text

パッケージ構成 #goconnect

Slide 27

Slide 27 text

#goconnect

Slide 28

Slide 28 text

#goconnect

Slide 29

Slide 29 text

#goconnect

Slide 30

Slide 30 text

注釈 Go 本体のコードを引用しますが スライドの都合で省略しています 詳しくはURLを添付しているので そちらをご参照ください #goconnect

Slide 31

Slide 31 text

go test コマンド実行 #goconnect

Slide 32

Slide 32 text

概要 go コマンドが test サブコマンドを呼び テスト処理を実行する #goconnect

Slide 33

Slide 33 text

軽く解説 #goconnect

Slide 34

Slide 34 text

#goconnect ざっくりの流れ... go コマンド → test サブコマンド https://github.com/golang/go/blob/go1.26.2/src/cmd/go/main.go

Slide 35

Slide 35 text

#goconnect ざっくりの流れ... func runTest(...) に到達 https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/test/test.go

Slide 36

Slide 36 text

rutTest() 関数は パッケージごとに build → run → print を行うオーケストレーション #goconnect

Slide 37

Slide 37 text

build 処理にて テスト対象ファイル・関数を収集する Import(...) 関数に到達 #goconnect

Slide 38

Slide 38 text

#goconnect ファイルの分類・関数の収集

Slide 39

Slide 39 text

概要 ファイル名とパッケージ宣言で分類 テスト名をもとにテスト関数を収集 #goconnect

Slide 40

Slide 40 text

ファイルとパッケージの分類 ファイル名が _test.go で終わるか パッケージ宣言が _test で終わるか #goconnect

Slide 41

Slide 41 text

グルーピング ファイル名 パッケージ宣言 GoFiles ex) calc.go ex) package calc TestGoFiles ex) calc_test.go ex) package calc XTestGoFiles ex) calc_x_test.go ex) package calc_test #goconnect

Slide 42

Slide 42 text

グルーピング ファイル名 パッケージ宣言 GoFiles ex) calc.go ex) package calc TestGoFiles ex) calc_test.go ex) package calc XTestGoFiles ex) calc_x_test.go ex) package calc_test pxtest ptest #goconnect

Slide 43

Slide 43 text

各パッケージからテスト関数を AST により収集 #goconnect

Slide 44

Slide 44 text

#goconnect ptest, pxtest を for ループ https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L584-L593

Slide 45

Slide 45 text

#goconnect テスト関数を管理する構造体 https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L626-L638

Slide 46

Slide 46 text

#goconnect ファイル内の関数をループ https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L702-L773

Slide 47

Slide 47 text

#goconnect 命名規則チェック 関数の型チェック https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L702-L773

Slide 48

Slide 48 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L584-L593

Slide 49

Slide 49 text

#goconnect 型チェック ジェネリクス禁止 https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L775-L788

Slide 50

Slide 50 text

#goconnect 戻り値・引数チェック ポインタチェック 型名チェック https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L557-L579

Slide 51

Slide 51 text

以下のテスト関数を収集 ptest.TestAdd(t *testing.T) ptest.TestSub(t *testing.T) pxtest.TestAdd(t *testing.T) #goconnect

Slide 52

Slide 52 text

_testmain.go の生成 #goconnect

Slide 53

Slide 53 text

概要 テスト関数を実行する main () 関数を生成する #goconnect

Slide 54

Slide 54 text

Go Template を使ったコード生成 testFuncs 構造体を受け取る testmainTmpl #goconnect

Slide 55

Slide 55 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L790-L862

Slide 56

Slide 56 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L790-L862

Slide 57

Slide 57 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L790-L862

Slide 58

Slide 58 text

#goconnect Go Template によるコード生成 https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/load/test.go#L617-L624

Slide 59

Slide 59 text

生成されるテスト実行コード #goconnect

Slide 60

Slide 60 text

_testmain.go の確認方法 go test -work WORK=xxxx #goconnect

Slide 61

Slide 61 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/testing/testing.go#L2319-L2329

Slide 62

Slide 62 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/testing/testing.go#L2340-L2487

Slide 63

Slide 63 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/testing/testing.go#L2551-L2598

Slide 64

Slide 64 text

t *testing.T は自動生成するコードで テストを動かす MainStart(..).Run() 関数 からやってくる! #goconnect

Slide 65

Slide 65 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/testing/testing.go#L1876-L2042

Slide 66

Slide 66 text

ビルド #goconnect

Slide 67

Slide 67 text

概要 リスト化したパッケージをもとに 実行可能バイナリを生成する #goconnect

Slide 68

Slide 68 text

省略! go build と同じ仕組みを利用 バイナリの命名が異なる (.test が付与) #goconnect

Slide 69

Slide 69 text

実行 #goconnect

Slide 70

Slide 70 text

概要 生成したテストバイナリを 子プロセスとして実行 #goconnect

Slide 71

Slide 71 text

#goconnect https://github.com/golang/go/blob/go1.26.2/src/cmd/go/internal/test/test.go#L1435-L1774

Slide 72

Slide 72 text

テスト実行完了! #goconnect

Slide 73

Slide 73 text

まとめ #goconnect

Slide 74

Slide 74 text

#goconnect go test は黒魔術ではなく go template と AST を愚直に使った コード自動生成による main 関数の実行

Slide 75

Slide 75 text

2020.04 2021.04 2022.11 Kotaro Otaka おーたかこーたろー / @otakakot Web Engineer 新卒入社 Hello Golang! Web Engineer @株式会社ビットキー Gopher6年生 #goconnect

Slide 76

Slide 76 text

おわり またどこかで お会いしましょう!