Open8

PostgreSQLをバックエンドとしたアプリのテスト方法を求めて

MURAOKA TaroMURAOKA Taro

バックエンドにPostgreSQLを使った(Web)アプリのより良い単体テスト方法を探っている。

アプリはGo製、ORMにはxormを用いてる。

MURAOKA TaroMURAOKA Taro

もっとも原始的に、ローカルにPostgreSQLをインストールしてpg_ctlでテスト毎、もしくはpackage毎にDBを作ってしまうことを考えた。

結果 koron-go/pgctl が生まれた。

これはテスト毎にDBインスタンスが立つのでテストとしては理想的だったが、いかんせんインスタンスの起動が遅いので気軽にユニットテストを実行する気になれなかった。

MURAOKA TaroMURAOKA Taro

テスト用のPostgreSQLインスタンスを起動しっぱなしにし、各テストはデータが被ったり残ったりしないように棲み分けることを考えた。

テスト間に薄い依存ができてしまったのと、テストデータの掃除に失敗すると復帰が面倒なのと、さらにはパッケージを超えて並列にテストを実行すると問題が起こりやすい。

使えなくはない(実際に一部では使ってる)があまり良くもない。

MURAOKA TaroMURAOKA Taro

ユニットテストではPostgreSQLの代わりにSQLite3を使ってみた。どうせORMをかぶせてるんだからORMがサポートしているDBならなんでも良いやろという発想。

多くの機能はこの方法で問題なかったが、一部のPostgreSQL固有の機能(jsonb, postgis等々)に依存した機能は当然NGだった。

またconstaintに引っかかるような半正常系についても、PostgreSQLドライバー固有のエラーを解釈しており、xormでは処理されてないこともありテストができなかった。SQLite3はどうもconstraintに引っかかったフィールド名などを取るのが難しそう。

ただし速度やテスト間の独立性など満足できた点は多い。現実的にはこのあたりが落としどころだと考えている。

MURAOKA TaroMURAOKA Taro

postliteを調べる過程で jackc/pgmock を知った。PostgreSQLのプロトコルレベルでmockingするテストに使えそう。

発行されるSQL文の文字レベルでテストを記述する必要があるのと、本来興味がないPostgreSQLプロトコルレベルの知識を必要とするのでtoo much感が強い。

まぁ1回やってしまえばかなりの部分を使いまわしできるとは思うが、面倒さに見合うかイマイチわからない。ただテスト用にfixtureを管理しなくて良いという魅力(?)もある。いややっぱダメかな。

MURAOKA TaroMURAOKA Taro

教えてもらったやつ。

https://twitter.com/hnakamur2/status/1510894752375271428

DATA-DOG/go-txdb - 実物のDBを使いつつ、各テストのコネクションをトランザクションで独立に保つ仕組みっぽい。

テスト間の薄い依存を解決する手段としては納得。ただPostgreSQLのインスタンスと、スキーマのセットアップは要ることになる。

残念ながら僕の用途ではあんま導入するメリットがなさそう。