ユニットテストについてお勉強中の阿部です。
今回はPGroongaのユニットテストについて説明します。 どのようなツールを使って、どのようなテストをしているのかと新たにテストを追加する方法を説明します。
Groonga開発者に聞け!(グルカイ!)第60回でも 解説しているので、あわせてご覧ください!
PGroongaのユニットテストで使っているツール
PGroongaでは以下の2つを使っています。
pg_regress
- PostgreSQLに含まれているリグレッションテストツール
- SQLを実行して期待通りの結果が得られるかテストできる
- 独自のテストツール
- ストリーミングレプリーケーションのテストが便利にできる
- クラッシュしたときのテストが便利にできる
pg_regress
を使ったテストで十分な場合がほとんどだと思いますが、PGroongaではレプリーケーションをしたときの
プライマリー側の挙動のテスト、スタンバイ側の挙動のテストや、PGroongaがクラッシュした場合の挙動のテストなども
必要でした。
そのようなテストの場合pg_regress
ではテストを書くのが大変だったため、独自のテストツールを使って
テストを実行しています。
以降で「pg_regress
」と「独自のテストツール」の特徴と新規でテストを追加する方法ついて説明します。
pg_regress
: 概要
「テストしたいSQL」と「期待される実行結果」の2つのファイルを用意すればテストできます。 「テストしたいSQL」を実行した結果と「期待される実行結果」が一致しているかをテストします。
具体例を見るのが手っ取り早いので、以下に具体例を記載します。
「テストしたいSQL」例の一部:
SELECT id, content
FROM memos
WHERE content &@~ 'rdbms OR engine';
全文掲載すると長くなるのでひとつの SELECT
のみ掲載しました。
このSQLを実行して、以下の結果と同じになるかをテストする非常にわかりやすいテストです。
「期待される実行結果」例の一部:
SELECT id, content
FROM memos
WHERE content &@~ 'rdbms OR engine';
id | content
----+------------------------------------------
1 | PostgreSQL is a RDBMS.
2 | Groonga is fast full text search engine.
(2 rows)
pg_regress
: 新規でテストを追加する
実は上記の説明は少し正確ではありません。
「テストしたいSQL」と「期待される実行結果」の2つのファイルを用意
と書きましたが、実はテストを新規で追加するときは「テストしたいSQL」だけ用意すれば良いです。
流れは以下の通りです。
- 「テストしたいSQL」を用意する
- PGroongaでいうと
sql/
以下に新たな.sql
ファイルを追加
- PGroongaでいうと
- 「テストしたいSQL」のみを追加した状態で
pg_regress
を実行 - 「期待される実行結果」を用意していないので、実行結果との差分が表示される。その内容を確認
- 「期待される実行結果」がないので実行結果の全文が表示される。それが期待通りか確認する
- 3で表示された結果が期待通りであれば、その結果から「期待される実行結果」を作る
- PGroongaでいうと
results/
以下にテスト実行結果が出力されるsql/full-text-search/vacuum.sql
のテスト実行結果であれば、results/full-text-search/vacuum.out
に出力される
- それをコピーして
expected/
以下に配置するsql/full-text-search/vacuum.sql
のテスト実行結果であれば、results/full-text-search/vacuum.out
をexpected/full-text-search/vacuum.out
にコピーする
- 以上で「期待される実行結果」の作成が完了
- PGroongaでいうと
pg_regress
を実行してテストがパスすることを確認する
ということで、「テストしたいSQL」のみ用意してpg_regress
の結果から「期待される実行結果」を作れます。
これで新たなテストの追加が完了です。
独自のテストツール: 概要
Rubyで書かれた独自ツールです。 細かく説明すると長くなるので、便利ポイントを3つだけ紹介します。
レプリーケーションのテストが簡単にできる
https://github.com/pgroonga/pgroonga/blob/3.2.1/test/test-streaming-replication.rb
class StreamingReplicationTestCase < Test::Unit::TestCase
include Helpers::Sandbox
setup :setup_standby_db
teardown :teardown_standby_db
...
end
setup :setup_standby_db
、teardown :teardown_standby_db
と書くとレプリーケーションの
スタンバイサーバの用意とお片付けもしてくれます。(プライマリーサーバは明示的に指定しなくても毎回起動してくれます。)
これらとrun_sql
やrun_sql_standby
を使うことでレプリケーションのプライマリー側、スタンバイ側の挙動のテストが簡単に行えます。
補足: run_sql
、run_sql_standby
メソッド名から想像できると思いますが run_sql
はクエリを実行します。これはプライマリーサーバでクエリを実行します。
run_sql_standby
メソッドもあり、こちらを実行するとスタンバイサーバでクエリを実行します。
設定変更を簡単にできる
その都度PostgreSQLの設定を変えてテストしたいときがあります。
pg_regress
は起動済のPostgreSQLサーバに対してテストを実行するので、そういった場合にテストしにくいです。
https://github.com/pgroonga/pgroonga/blob/3.2.1/test/test-pgroonga-crash-safer.rb
def additional_configurations
<<-CONFIG
pgroonga.enable_crash_safe = yes
pgroonga.enable_wal = yes
pgroonga.log_level = debug
pgroonga_crash_safer.flush_naptime = #{flush_naptime}
pgroonga_crash_safer.log_level = debug
CONFIG
end
additional_configurations
というメソッドを定義して、そこに設定したPostgreSQLの設定を書くと、
テスト実行時にその設定で起動したPostgreSQLサーバでテストが実行できます。
ログを確認できる
https://github.com/pgroonga/pgroonga/blob/3.2.1/test/test-vacuum.rb
「バックグラウンドで動くモジュール」を開発していると、 ログの内容もテストしたくなります。 そのような場面でもこの独自のテストツールは便利です。
pgroonga_log = @postgresql.read_pgroonga_log
assert_equal(["pgroonga: unmap DB because VACUUM was executed"],
pgroonga_log.scan(/pgroonga: unmap.*$/),
pgroonga_log)
@postgresql.read_pgroonga_log
でPGroongaのログの内容を取得できるのでそれを使ってテストできます。
PostgreSQLのログであれば@postgresql.read_log
で取得できます。
独自のテストツール: テストを追加する
上記で説明した独自の便利メソッドを駆使して追加します。
基本的にはRubyのtest-unit
なので、test-unit
を書くときと書き方は一緒です。
かなり簡単に書くとrun_sql
でクエリを実行する、それが期待通りかassert_equal
するテストを追加します、
という感じです。
...
setup do
# CREATE TABLEなど準備
# ...
end
test "example" do
# 期待される結果
expected_output = "..."
expected_error = "..."
# run_sqlで実際に実行
acutal_output, actual_error = run_sql("SELECT * FROM example")
# テストする
assert_equal([expected_output, expected_error]
[acutal_output, actual_error])
end
...
まとめ
詳細を説明するにはスペースが狭すぎたので概要の説明のみにとどめましたが、PGroongaのユニットテストについて説明しました。
pg_regress
はPGroonga以外でも使われているのでぜひご活用ください!
PGroongaの独自のテストツールは非常に簡単にテストが書けて開発スピードが上がります。 そのようなテストツールの開発などもサポートいたしますので、ユニットテストでお困りの際は お問い合わせよりお問い合わせください。