ククログ

株式会社クリアコード > ククログ > pg_regressは期待値ファイルを複数指定できる

pg_regressは期待値ファイルを複数指定できる

PostgreSQLにいくつかパッチを投げている須藤です。パッチのレビューの中で、PostgreSQLのリグレッションテストツールpg_regressに今まで知らなかった機能があったことを知ったので紹介します。

pg_regress

pg_regressはいわゆるエンドツーエンドのテストツールです。PostgreSQLクライアントでサーバーに接続してSQLを実行し、そのときの実行結果があらかじめ用意してある期待値と同じになっているかどうかでテストします。MySQLでいえばmysqltest、Groongaでいえばgrntest相当のツールです。

Webアプリケーションのテストではエンドツーエンドのテストは実行時間が長くなりがちでできるだけ書きたくないテストになりやすいですが、データベースのテストの場合はそうでもありません。たしかに、Cで書いた単体テストのほうが実行時間が短くなりやすいですが、CではなくSQLでテストを書けるので、エンドツーエンドのテストの方がメンテナンスしやすいです。また、実際にユーザーが使うときと同じ一連の処理を少ないテストでカバーできることもメンテナンスのしやすさにつながります。Groonga・Mroongaは、昔は単体テストも書いていましたが、今はエンドツーエンドのテストしか書いていません。

ということで、PostgreSQLのテストを書くにあたりすごく便利なツールがpg_regressです。

pg_regressが苦手なところ

便利といってもなにもかもpg_regressでカバーできるわけではありません。pg_regressはSQLでテストを書くので、SQLで書かないようなことは苦手です。

たとえば、SQLを発行する前の接続関連のテストは苦手ですし、レプリケーションのように複数の接続にまたがるようなケースや、PostgreSQL起動時に設定をしなければいけないようなケースも苦手です。

環境によって結果が変わるようなケースも苦手だと私は思っていました。

pg_regressはPostgreSQLクライアントとしてpsqlを使うので、SQLではできないけどpsqlでできることならできます。たとえば、条件分岐をできます。SQLでもplpgsqlを使えば条件分岐をできますが、psqlの方がもっとがんばれる気がします。(気のせいかもしれません。)

そんな便利機能を使えば、環境によって結果が変わるようなケースでも対応できることがあります。たとえば、PGroongaではPostgreSQLのバージョンによって結果が変わるケースを\g |sedで結果を正規化して環境が変わっても結果が同じになるようにして対応していました。デバッグしやすいHTMLのテストの書き方の「assert_match問題」と同じアプローチです。

しかし、古いPostgreSQLでは機能がなくてエラーになるケースもあり、そのような場合は結果を正規化することはできません。そのようなケースにどう対応していたかというと、該当のテストファイルを削除してテストを実行しないようにしていました。

でも、そんなことをする必要はなかったのです!

期待値ファイル

pg_regresssql/test.sqlを実行し、その結果を、事前に用意しておいた期待した結果が入ったexpected/test.outの内容と比較します。同じであれば成功、そうでなければ失敗です。私はこの期待値ファイルを各テストごとに1つだけ用意しなければいけないと思っていました。

が、実は、複数の期待値ファイルを用意して、そのどれかと同じ内容であれば成功、というようにできたのです。

この例の場合ではexpected/test.outだけでなく、expected/test_1.outのように_[0-9]を追加したファイルも用意しておくことができたのです。0から9まで使えて、追加で10個用意できますが、PostgreSQL本体のテストでは_1_2しか使っていませんでした。

ということで、通常の期待値はexpected/test.outとして用意し、特別な環境用の期待値ファイルをexpected/test_1.outとして用意することでどの環境でもいい感じにテストを実行することができます。

grntestではまた違った形で環境に依存するテストをいい感じに扱えるようにしていますが、こういうアプローチもあるなぁと思ったのでした。

まとめ

みなさんは、レビューされるときはどんな気持ちでレビューされているでしょうか。レビュアーからの指摘をそのまま反映することでレビューを通すことを目指す!というのも一つのやり方だとは思いますが、レビューから学ぶという気持ちでのぞんでみてもいいかもしれません。

ちなみに、私がこのpg_regressの機能を知ったレビューコメントはRe: confusing / inefficient "need_transcoding" handling in copyでした。