コンテンツにスキップ

テスト用 DB のライフサイクルを選ぶ

アプリと検証用の接続は、同じテスト用 DB に向けます。アプリがいつクライアントを作るかを決めると、その DB をいつまで維持するかも選べます。

アプリの形 分離方式 並列実行 アプリに渡すもの
テストごとにクライアントを作る テストごとの fork 独立した書き込みテストを同時実行できる Go の一つの fx.For(t)、Python の pgmem_test_dsn、Java の TestDatabase、Node の withFork の URL
クライアント、pool、import 時の ORM を保持する 固定接続先で、書き込みテスト後に reset 読み取りも含め、その接続先では直列実行 Python の pgmem_shared_dsn と reset マーカー、または Node のファイル登録と withTestReset
準備済みのデータを読むだけ 接続先を共有 同じ接続先を reset・書き込みする処理がなければ同時実行できる Go の共有 helper、Python の shared/class DSN、Java の CLASS スコープ、Node のファイル用 fork
デプロイ先と同じネットワーク経路を通したい TCP または Unix stream socket 上で選んだ分離方式による Go fixture の Transport。pgmemprocess は DB を所有する子プロセスで起動する

Go の For(t) を二度呼ぶと、意図的に二つの DB ができます。戻り値を保持し、アプリ用と検証用の handle をそこから取得します。Python のマーカーは client fixture が接続する前に適用され、既に別の DSN を保持したクライアントの接続先は変更できません。Node はアプリの import 前に register を実行します。

Go の実行場所と接続方式は別々に選べます。組み込みでは net.Pipe、TCP、Unix socket を使えます。軽量な外部プロセスクライアントは組み込みエンジンを import せず、TCP または Unix socket で接続します。AF_UNIX の stream socket に対応する Windows でも使えます。

リソース 管理する側 解放するタイミング
プロセス、テンプレート、基準 snapshot テスト fixture / global setup 全クライアントとテスト用 fork の終了後
独立した fork テストごとの fixture または明示的な callback テストのクライアントを閉じた後
共有 fork クラス、ファイル、スイート用 fixture 共有接続先を使う処理がすべて終わった後
HTTP サーバー、driver pool、ORM engine/session アプリの fixture リクエストを止め、fork の解放前にクライアントを閉じる
Valkey / OpenSearch のリソース、アプリのキャッシュ 各サービスの fixture そのサービスの分離方式に従う

先の close が失敗しても、管理する残りのリソースの解放を試みます。Go はエラーを結合し、Node は AggregateError、Java は suppressed exception を使います。Python の context manager は Python 3.9 以降で CleanupError.primary_error と .cleanup_errors を公開します。テスト本体の失敗と後片付けの失敗が両方残ります。

自動で行う操作 既定値 設定
Go fixture の fork 取得。直接取得する helper も含む 30 秒 ForkTimeout
Python function/class/shared fixture の fork 取得 30 秒 pgmem_fixture_options["fork_timeout"]
Node register/useFork/Jest の fork 取得 30 秒 forkTimeoutMs または PGMEM_FORK_TIMEOUT_MS
Python reset モード 5 秒 reset_timeout
Node のワーカー再利用時の reset 5 秒 resetTimeoutMs または PGMEM_RESET_TIMEOUT_MS
Java の注入する fork の取得 指定しないと無期限 .forkTimeout(Duration)

手動で snapshot から fork する API は、無期限に待つ形式も維持しています。使うときは context の期限や timeout を指定できます。fork 取得は空き枠を待ち、snapshot と reset は開いたトランザクションの終了を待ちます。一方の timeout を延ばしても、もう一方には影響しません。共有 fork も枠を占有します。

共有する読み取りにガードを付ける

Section titled “共有する読み取りにガードを付ける”

ガードは convenience 接続の開始時に default_transaction_read_only=on を設定します。通常の永続データへの書き込みは SQLSTATE 25006 で失敗し、準備済みのデータは引き続き読めます。

組み込み先 有効にする設定
Go 組み込み / 外部プロセスの共有 helper SharedReadOnly: true
Python の選択された shared / class DSN pgmem_fixture_options に shared_read_only: True
Java CLASS スコープ/@PgmemTest(fork = false) の TestDatabase、DataSource、JDBC URL 注入 .sharedReadOnly(true)
Node の注入するファイル用接続 URL useFork({ readOnly: true })、Jest の readOnly: true、または PGMEM_READ_ONLY=true

これは誤操作を検出するガードです。権限による境界ではなく、利用者はセッションの既定値を変更できます。一時テーブルへの書き込みもでき、素の server / fork URL も取得できます。Python の reset クライアントと、独立した書き込み fixture は書き込み可能なままです。Node のガード付きファイルでは読み取りテストを行い、書き込みには別の書き込み可能な fork を使います。アプリのクライアントを作る前に有効にしてください。

状態 pgmem の reset の作用 アプリ側の対応
DB のスキーマ、行、sequence 指定した snapshot に戻る 開いたトランザクションを先に commit / rollback する
接続先と対応する開いたクライアント socket 維持する 直列の reset モードでは pool を保持できる
driver / ORM の identity cache サーバーからは消去しない テストごとに session を作るか、キャッシュしたオブジェクトを expire する
アプリのメモリやメモ化した値 戻さない 状態を消すか、アプリを作り直す
Valkey のキー 戻さない Valkey fixture の cleanup / reset を使う
OpenSearch の index 戻さない OpenSearch fixture の cleanup / reset を使う
既に予約されたアプリの処理 キャンセルしない reset 前にバックグラウンド処理を待つか停止する

reset の間、その接続先を共有するテストは読み書きできません。同時に書き込むテストには、アプリごとに別の fork とクライアントを渡します。アプリ経由のサンプルと失敗の調べ方も参照してください。