Groongaの回帰テストで既知の差分を吸収するには - 2019-07-22 - ククログ

ククログ

株式会社クリアコード > ククログ > Groongaの回帰テストで既知の差分を吸収するには

Groongaの回帰テストで既知の差分を吸収するには

はじめに

オープンソースのカラムストア機能付き全文検索エンジンに、Groongaがあります。 Groongaを使うと全文検索機能付き高性能アプリケーションを開発することができます。

Groongaは毎月29日(肉の日)ごろに新しいバージョンをリリースしています。 そう頻繁なことではありませんが、非互換な変更が入ったりすることもあります。

バージョンアップによって、Groongaを利用するアプリケーションで検索結果が変わっていたりすると大変です。 そんなときに便利なのが、groonga-query-log です。 groonga-query-log には回帰テスト用のツールが含まれているので、古いGroongaと新しいGroongaに対して既存のクエリーログを使って回帰テストが実行できます。 ただ、そこそこ古いGroongaとの回帰テストの結果を比較すると、そのままでは大量に差分がでてしまって困ることがあります。

今回は、回帰テストを実行する際に既知の非互換な差分は吸収しつつ、本当に必要な差分のみを検出するやりかたを紹介します。

groonga-query-log とは

groonga-query-log はGroongaのクエリーログに関する便利ツールを集めたものです。 groonga-query-log できることについては、いくつか記事がありますのでそちらを参考にしてみてください。

回帰テストに関しては、groonga-query-log-run-regression-test というスクリプトが含まれているのでそれを使います。

回帰テストの実行のしかた

groonga-query-log-run-regression-testを使って回帰テストを実行できます。

groonga-query-log-run-regression-testはgroonga-query-logに含まれています。

% gem install groonga-query-log

回帰テストを実行するには、Groongaのダンプデータと回帰テストの対象となるクエリーログが必要です。

groonga-query-log-run-regression-test \
  --old-groonga=(比較元のGroongaのパス) \
  --new-groonga=(比較先のGroongaのパス) \
  --input-directory=(ダンプやクエリーログのあるディレクトリ)

詳細については、ドキュメントを参照してください。

差分を吸収するためのオプションの解説

回帰テストの差分を吸収するためのオプションがいくつかあります。

  • --ignore-drilldown-key

  • --vector-accessor

  • --rewrite-vector-equal

  • --rewrite-vector-not-equal-empty-string

  • --rewrite-nullable-reference-number

  • --nullable-reference-number-accessor

  • --rewrite-not-or-regular-expression

それぞれのオプションの使い方を説明します。

--ignore-drilldown-key

Groonga 7.1.0でベクターカラムのドリルダウンをサポートしたことによる影響を無視するためのオプションです。 7.0.9以前の古いバージョンのGroongaでは、正しい結果を返していませんでした。 7.0.9以前の古いバージョンとの7.1.0以降のGroongaを比較する際に、ドリルダウン対象となっているベクターカラムを指定します。

--vector-accessor

後述する --rewrite-vector-equal--rewrite-vector-not-equal-empty-string を適用する対象のベクターカラムを指定します。 対象が複数あるなら、このオプションを複数指定します。

--rewrite-vector-equal

ベクターカラムに対して vector == ... で検索しているクエリー(正しくない使い方)を vector @ ... に書き換えてテストを実行します。 クエリーで書き換える対象は --vector-accessor で指定します。

古いGroongaでは、vector == ... で検索するときは先頭の要素と同じならヒットするようになっていました。(ベクターカラムをスカラーカラムとして扱っていてたまたま動いていた) 新しいGroongaではヒットしなくなっているので差分が発生します。その差分を吸収するために指定します。

--rewrite-vector-not-equal-empty-string

ベクターカラムに対して vector != "" で検索しているクエリー(正しくない使い方)を vector_size(vector) > 0 に書き換えてテストを実行します。 クエリーで書き換える対象は --vector-accessor で指定します。 vector_sizeは Groonga 5.0.3以降で使えるものなのでそれより古いGroongaと新しいGroongaとの回帰テストには使えません。

--rewrite-nullable-reference-number--nullable-reference-number-accessor

古いバージョンでは参照先のレコードが存在しないとき、そのレコードのカラムの値のデフォルト(数値なら0とか)を使ってfilterを処理していました。 新しいバージョンでは必ず false になるため、同等の内容になるように以下のようにクエリーを書き換えます。

(参照型のカラム) <= 10000 というクエリーは (参照先の_key == null ? 0 : 参照型のカラム) <= 10000 に置き換えます。

--rewrite-not-or-regular-expression

正規表現で否定先読みを用いた検索で、古いGroongaと新しいGroongaで差分がでないようにします。 &! マッチしたレコードを除く演算子と @ 全文検索を組み合わせてGroonga 5.0.7とそれ以前で挙動が同じになるようにします。

例えば、column1 @ "keyword1" && column2 @~ "^(?!.*keyword2|keyword3|...).+$'column1 @ "keyword1" &! column2 @ "keyword2" &! column2 @ "keyword3" &! ...' に置き換えてテストを実行します。

まとめ

今回は、回帰テストを実行する際に既知の非互換な差分は吸収しつつ、本当に必要な差分のみを検出するやりかたを紹介しました。