リグレションテストの説明と解析
リグレションテストとは、PostgreSQLで組み込み実装されている SQLの包括的なテストの一式です。リグレションテストでは、標準なSQL操作に加えて PostgreSQLの拡張SQL機能もテストします。 これらのものはJolly ChenとAndrew Yuによって始めに開発され、その後 Marc FournierとThomas Lockhartによって改訂され、より使い易く、またより理解しやすい 機能的な編成としてまとめられました。PostgreSQLv6.1以降 リグレションテストは公式リリース版に含まれています。
リグレションテストはすでにインストールされでサーバで動いているものに 対して、また、ビルドツリー内に一時的にインストールされたものに使用できます。 さらに、テストを行う際に、"parallel"と"sequential"モード があります。"sequential"モードでは、1つずつテストスクリプトを 実行します。"parallel"モードでは複数のサーバプロセスを 実行し、テストを並行的に実行します。"parallel"テストでは プロセス間通信とロック機能が正常に作動しているかをテストします。 歴史的理由により、"sequential"テストは存在するインストールに 対して行われ、"parallel"テストでは一時的にインストールされたものに 対して行われます。これらに技術的根拠はありません。
リグレションテストをインストール前の、ビルドを行った後に行う場合は ディレクトリの一番最上階で
$ gmake checkと入力して下さい。(または、src/test/regressディレクトリに 移動して、そこで実行して下さい。)これらを実行したら、まず プラットフォームに依存した"期待される結果の(expected)"ファイルや、 ユーザ定義のトリガ関数のサンプルなどの補助ファイルをいくつか作成し、 それからテストドライバのスクリプトを実行します。 終了したら、下記のような表示がされるはずです。
====================== All 76 tests passed. ======================上記が表示されなければ、テストは失敗したことになります。 詳細はSection 12.1をご覧下さい。
Note: この方法で一時的サーバを起動させるため、ルートユーザでは作動しません。 (サーバはルートでは起動しません。)しかし、ルートでビルドを行ったとしても、 すべてを最初からやり直す必要はありません。リグレションテストの ディレクトリを他のユーザでも書き込める権限を与え、そのユーザになり、 テストを再実行することにより、テストが可能です。例えば、
root# chmod -R a+w src/test/regress root# su - joeuser joeuser$ gmake check(この方法に関してのセキュリティ問題として、テストを実行している際に 別のユーザがこのテストを変更することが可能ということです。 ユーザ権限を与える際には充分に注意して下さい。)また、インストール後にテストを実行することも可能です。
Tip: システムによっては、デフォルトのBourne互換シェル(/bin/sh) は多くの子プロセスを並行的に実行すると動作が不安定になることがあります。 これは並行テストを失敗させるか、フリーズさせてしまう可能性があります。 このような場合、コマンドラインで別のBourne互換シェルを指定して下さい。 下記に例を示します。
$ gmake SHELL=/bin/ksh check
インストール後にテストを実行するには(Chapter 1を 参照して下さい)、 Chapter 3で明記されているように、データ領域を初期化し、 サーバを起動させて下さい。その後、下記のように入力して下さい。
$ gmake installcheckテストは、環境変数、PGHOSTとPGPORTで指定がない限り、 ローカルホストのサーバに接続し、ディフォルトのポート番号を使用します。
適正に導入されかつ全ての機能が使用できるPostgreSQL であっても、 プラットフォームで生じる浮動小数点の表現構造と時間帯のサポート などの誤差で失敗することがあります。現在のテストは単純な "diff" アルゴリズムを使用して結果の検証を行っているためプラットフォームの 些細な違いにも反応します。結果が「失敗」となったら 実際の結果と予測した結果の差を調査して下さい。それらの差異が重大では ないことが判明することもあります。しかし、すべてのプラットフォームで すべてのテストが成功するように、改善するように努力されています。
実際のリグレションテストの結果はsrc/test/regress/results ディレクトリのファイルに書かれています。テストではdiffを 使用して、結果ファイルとsrc/test/regress/expectedディレクトリの 結果とを比較します。あらゆる差異は src/test/regress/regression.diffsに 保存され、後に参照することができます。(あるいは、ご自分でdiffを 実行することもできます。)
リグレションテストのいくつかは故意に無効な入力値を使用します。 エラーメッセージはPostgreSQLのコードに よるもの、または使用しているプラットフォームからのものがあります。 後者の場合、プラットフォームによって違いがありますが、 似たような内容であるはずです。これらのメッセージの違いにより リグレションテストは失敗する可能性がありますが、 これらは検査で確認できます。
リグレションテストは純粋な"C"ロケールで実行するように 実装されています。リグレションテストドライバはサーバをCロケールで 起動させるので、これは一時的インストールのものに対して テストを実行する時などにも特に問題にはならないはずです。 しかし、既にインストールされた、Cロケールではないサーバに対して テストを実行する際には、文字列のソート順の規則の違いや 数を通貨型に変換するときなどに違いが生じる可能性があります。
いくつかのロケールでは結果の違いは少なく、検査することによって 簡単に確認することができます。しかし、数値のフォーマットの規則を 変更されたロケールでは(特にカンマや小数点を置き換える場合) データ値の入力で失敗する場合があり、したがって、後のテストで多くの 差異が生じる場合があります。
ほとんどの日付と時刻の結果はタイムゾーンの環境に依存します。 差異結果のファイルはPST8PDTタイムゾーン(カリフォルニア・バークレイ)を 基準に生成されます。したがって、テストがこのタイムゾーンで実行されなければ 明らかに失敗に終ります。リグレションテストのドライバは結果が 正しくなるように、PGTZをPST8PDTに 設定します。しかし、使用しているシステムはPST8PDTタイムゾーンの ライブラリを提供している必要があります。提供されていなければ タイムゾーンに依存しているテストは失敗に終ります。 使用しているマシンがこの機能をサポートしているかの確認は 下記の方法で行うことができます。
$ env TZ=PST8PDT date上記のコマンドを実行したら、PST8PDTタイムゾーンでの現在のシステム時間を 返すはずです。もしPST8PDTデータベースが存在しなければ、 GMT時間で返している可能性があります。PST8PDTタイムゾーンが 存在しなければ、明示的にタイムゾーンのルールを設定することができます。
PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
ローカルなタイムゾーンのルールの設定に推奨された構文を受けつけない システムがあります。それらのマシンでは違ったPGTZ 設定を使用する必要があります。
古いタイムゾーンのライブラリを使っているシステムでは1970年以前の 夏時間変更に失敗し、PDT時刻がPSTで表現されてしまうという問題が あります。これは、テスト結果でローカル時間の違いを生じてしまいます。
"timestamp"テストの問い合わせで、夏時間変更日、または 前日/翌日に実行すると失敗する場合があります。これらの問い合わせは 昨日の夜中、今日の夜中、明日の夜中の間隔が24時間であるとしていますが、 夏時間が実行/解除された時には24時間の間隔がないためです。
64ビット(double precision型)の数値をテーブルの カラムから取り出して計算を行うテストがあります。 double precisionカラムにおける演算関数で は、異なった結果が発生する場合があることが知られています。 float8 と幾何型テストは特に、プラットホーム間、またはコンパイラの 最適化オプションによる小さな違いで問題を おこりやすくしています。これらのどこが異なっているのかは、 人間の目で実際に確かめる必要があります。通常は、小数点以下10桁目と いうことになるでしょう。
システムによっては、現在のPostgreSQLのコードの メカニズムの予想とは異るために、pow()と exp()でエラーを発生する場合があります。
地形データテストの実行にはカリフォルニアOakland/Berkleyの道路地図を 参照しています。地図データは多角形として表現されていて、頂点は double precision型の数(十進数での緯度と経度の)対で表されます。 まず最初にいくつかの地形データが格納されたテーブルが生成され、 多角形の交点演算子(##)を使って2つのテーブルを 結合するviewが生成され、そのview上でselectが行われます。
違うプラットフォームの結果を比較する場合は、小数点第2位、もしくは 第3位で違いが生じます。これらの違いが起こるSQL文は下記のものです。
SELECT * from street; SELECT * from iexit;
同じタプルの結果が期待されるファイルで記述されている順序とは異って いる場合がある場合があります。ほとんどの場合、これは厳密に言って バグではありません。ほとんどのリグレションテストは規則に厳しくなく、 各SELECT文に対してORDER BYを使用することはなく、タプル結果の順序は SQLの仕様でははっきりとは定義されていません。実際では、 同じソフトウェアで、同じデータを同じ問い合わせで参照しているので すべてのプラットフォームで同じ順序の結果が返され、よって、ORDER BYの 問題ではないと言えます。しかし、問い合わせによっては、プラットフォーム間の 順序の違いが起こる可能性があります。(順序の違いはCではないロケール設定 でも起こりえます。)
したがって、順序の違いが起こった場合、問い合わせにORDER BYが含まれていて 順序が影響を及ぼす場合以外は、それらは気にしないで下さい。 しかし、将来のリリースで、特定の問い合わせにORDER BYを追加して、 偽の"失敗"を取り除くためにご一報下さい。
このような問題を回避させるために、リグレションテストの SELECT文に順序関連のコマンドを挿入しない理由として、それを 行うと、必要がない問い合わせに対しても問い合わせ計画型を 実行しようとするなどのことからリグレションテストの意義を 逆に半減させることがあげられます。
"乱数"テストには、無作為の結果を出力することが 想定されているテストケースが、少なくとも1つあります。 この乱数により、5回から10回のうちに1回はリグレションテストが 失敗に終ることがあります。
diff results/random.out expected/random.out上記のコマンドを入力すると、数行程度の差異のみがあるはずです。 毎回失敗するのでなければ、気に止める必要はありません。 その一方で、リグレションテストを行い、毎回成功する 場合は気に止める必要があるかも知れません。