Share
Embed
synctest時代のhttptest Go 1.27で変わるHTTPサーバテストの裏側 / go conference2026 synctest and httptest
Go Conference 2026の登壇資料です。
https://gocon.jp/2026/
https://gocon.jp/2026/timetable/1264549/
Yoichiro Shimizu
September 11, 2026
Transcript
34 slides
-
自己紹介 清水 陽一郎 @budougumi0617 株式会社LayerX (2023/03~) 法人様向けクレジットカード・ETCカードを開発中 2026年4月からエンジニアリングマネージャ 一般社団法人Gophers Japan代表理事のひとり
2022年にGoの本を出版 24年3月 韓国語版出版 11/2 layerx.go #6 やるよ!! © LayerX Inc. -
今日の話の流れ と synctest のおさらい httptest.Server がなぜ synctest と併用できなかったのか Go 1.27の
httptest は何が出来るようになったのか httptest.NewTestServer は何をどうやって実現しているのか httptest © LayerX Inc. 6 -
synctestのおさらい synctest pacakge func Test(t *testing.T, f func(*testing.T)) それぞれのテストを独立した「バブル」と呼ぶ隔離環境で実行できる バブルの中で生成されたgoroutineの実行状況が管理される
バブルの中では独自の時間(fake clock)が流れる 10分後にタイムアウトしたらPASS、のようなテストでも一瞬で完了する func Wait() バブルの中のgoroutineがすべてdurably blockedになるのを待機する func Sleep(d time.Duration) © LayerX Inc. Go1.27で追加。 time.Sleep + synctest.Wait 8 -
synctestのおさらい 独立した時間が流れる「バブル」 synctest bubble fake clock G1 00:10:00 G3 G2
synctest bubble fake clock G4 00:25:00 G6 バブル内で生まれた goroutine を管理する 独自のfake timeを管理する それぞれのバブルは synctest.Test ごとに独立 G5 © LayerX Inc. 9 -
synctestのおさらい durably blocked ゴルーチンが永続的にブロックされている状態 バブル内で作成されたチャネルに対する送信または受信操作がブロックされている すべてのケースがバブル内で作成されたチャネルを対象とした select 文のブロック sync.Cond.Wait sync.WaitGroup.Wait
メソッドは、 sync.WaitGroup.Add メソッドがバブル内で呼び出された場合 time.Sleep バブル内のすべてのgoroutineがdurably blockedになると、 バブル内の時刻が進む(n秒のSleepなどが即時に解消される) synctest.Wait を使っていた場合は Wait が解除される © LayerX Inc. 10 -
synctestのおさらい non-durably blocked バブルの外からブロックが解除される可能性がある 次の操作はdurably blockedにはならない または sync.RWMutex のロック操作 ネットワーク操作のI/O待ち状態
システムコール sync.Mutex © LayerX Inc. 12 -
httptest.Server がなぜ synctest と併用できなかったのか non-durably blocked な処理は synctest と併用できない バブル内のすべてのgoroutineがdurably
blockedにならない bubble内の時刻が進まない synctest.Wait を使っていた場合はWaitが解除されない httptest.Server はサーバなのでネットワークI/Oからリクエストを待ち続ける そのためバブルの中でfake clockが進まない synctest.Wait も解除されない © LayerX Inc. 13 -
Go1.27のhttptest Go 1.27からのsynctestとhttptest リリースノートを読むと httptest.NewTestServer で synctest に対応したらしい! 正確に言うと @mazrean
さんのGo Proposal Weekly Digestで見かけて目をつけていた net/http/httptest The new NewTestServer function creates a Server configured to use an in-memory fake network suitable for use with the testing/synctest package. © LayerX Inc. ref: Go 1.27 Release Notes 17 -
Go 1.27のhttptestは何が出来るようになったのか どうやって実現しているのか Go1.26以前からあった httptest.NewServer で作成した(ほぼ通常の)HTTPサーバの処理の流れ 側 側 client server
http.Client http.Server http.RoundTripper Serve(net.Listener) *http.Transport TCPListener.Accept DialContext TCPConn © LayerX Inc. OS socket (loopback) TCPConn 21 -
Go 1.27のhttptestは何が出来るようになったのか httptest.NewServer と httptest.NewTestServer はどう違うの? 実はそこまで変わっていない internal/nettest パッケージの nettest.Listener
と nettest.Conn を使っている 側 側 client server http.Client http.Server http.RoundTripper Serve(net.Listener) *http.Transport DialContext client nettest.Conn © LayerX Inc. nettest.Listener.Accept connection pair in-memory server nettest.Conn 22 -
internal/nettest deep dive internal/nettest durably blockedと判定される処理だけを使って net.Listener と net.Conn の実装を提供している
バブル内で作成されたチャネルに対する送信または受信操作がブロックされている すべてのケースがバブル内で作成されたチャネルを対象とした select 文のブロック sync.Cond.Wait sync.WaitGroup.Wait メソッドは、 sync.WaitGroup.Add メソッドがバブル内で呼び出された場合 time.Sleep そのため internal/nettest を使っていても synctest のバブルが期待通りの挙動をしてくれる © LayerX Inc. 24 -
internal/nettest deep dive httptestはどう利用しているか サーバが保持するlistenerの NewConn メソッドでクライアントもコネクションを作成することで 同じ net.Conn の実体を参照する
© LayerX Inc. ref: server.go#L582-L588 25 -
internal/nettest deep dive internal/nettest.Conn 内部に2つのバッファとチャネルによるロック構造を持つ net.Conn の実装 クライアントが書き込み、サーバー側が読むバッファ サーバが書き込み、クライアントが読むバッファ サーバとクライアントが同じ
Conn を見ていればバッファ経由で送受信できる © LayerX Inc. ref: internal/nettest/conn.go 26 -
internal/nettest deep dive internal/nettest.NewListener *nettest.Listener は net.Listener インターフェースを満たす実装 状態管理しながらチャネルを使った Gate
というロック機能 作成したインメモリな Conn をプールする インメモリな net.Conn を作成する NewConn メソッドを持つ © LayerX Inc. 27 -
internal/nettest deep dive httptestはどう利用しているか クライアントが nettest.Listener のキューに nettest.Con をpushする サーバは
nettest.Listener のキューから nettest.Con をpopする 側 側 client server http.Client http.Server http.RoundTripper Serve(net.Listener) *http.Transport DialContext client nettest.Conn © LayerX Inc. nettest.Listener.Accept connection pair in-memory server nettest.Conn 28 -
まとめ synctest は決定的に非同期処理・時間依存のテストを書ける バブルとdurably blockedで成り立っている Go1.26までの httptest.Server はno-durably blockedなネットワーク通信をするので synctest
と併用できなかった Go1.27の httptest.NewTestServer を使えば synctest と併用できるようになった 実現している internal/nettest は思ったよりシンプル GoはGoで実装されているので読みやすい! © LayerX Inc. 31 -
参考資料 (1/3) Go 1.27 is released!(2026-08-19リリース) Go 1.27 Release Notes
net/http/httptest package documentation net/http/httptest: synctest support #76608 proposal: testing/nettest: in-memory implementations of net package interfaces #77362 © LayerX Inc. 32 -
参考資料 (2/3) CL 740100: testing/nettestのドラフト実装 net/http: use fake network for
HTTP/3 tests #80480 CL 801940: http3: rework registration to allow using a fake network CL 803380: net/http: rework HTTP/3 registration to allow using a fake network net/http のHTTP/3テストにおける PacketNet の利用 © LayerX Inc. 33 -
参考資料 (3/3) source internal/nettest.Listener source internal/nettest.Conn source internal/gate source Go
Blog: Testing concurrent code with testing/synctest net/http/httptest.Server © LayerX Inc. 34