最近、PostgreSQLスキーマの作成に使用できるデータスキーマの「スケルトン」
に関する記事を投稿しまし
た 。
回路を展開し、オブジェクトを作成するためのスクリプトに加えて、ストアド関数とそれらの単体テストの例がありました。

この記事では、pg_skeletonを例として使用し、pgTAPを使用してPostgreSQLストアド関数のテストを記述する方法を
詳しく説明します。
PgTAPは、名前が示すとおり、プレーンテキスト形式の
TAP(Test Anything Protocol)でテキストを出力します。 この形式は、多くのCIシステムで受け入れられています。
Jenkins TAPプラグインを使用しています。
拡張機能をインストールすると、データベース内にストアドファンクションが作成され(パブリックスキームではデフォルト)、テストの作成時に使用されます。 ほとんどの関数はさまざまなアサートです。 完全なリストは、
http :
//pgtap.org/documentation.htmlにあります。
test_userサンプル回路の関数をテストします。
最初に
pg_skeletonをインストールします 。 (pg_skeletonのインストール手順から、回路にテストをすぐに書き込みたい場合は、pgtap部分のみを実行し、データベースに拡張機能をロードします)
実際のプロジェクトで使用されているテストと同様のテストを作成し、より多くの異なるpgTAP関数を使用しようとしました。
テストを開始する前に、plan(int)関数を呼び出してテストの番号を指定する必要があります。
この例では、この呼び出しはファイルtest / tests / run_user.sqlにあります。
select plan(7+2+1);
この場合、7はuser_crud.sqlファイルから実行されたテストの数(テストf)、2はuser_schema.sqlファイルのテストの数、1はrun_user.sqlファイルで直接実行される1行のテスト(テストによる関数のカバレッジの確認)です。
pgTAPのドキュメントは、主に個々の選択クエリによって呼び出されるテストを扱っています-これは、回路のテスト、または副作用のない単純な関数のチェックに適しています(このようなテストはuser_schema.sqlにあります)。
ただし、複雑なシナリオをテストする場合、複数の関数を呼び出す必要があり、前の関数の結果が次の関数に転送される場合、複数のテストを含むスクリプトを実行するストアド関数にテストを組み合わせることができます。 そのような関数の例は、ファイルtest / functions_user.sqlにあります。
この関数は、多くの行を返すように宣言する必要があります。
create or replace function test.test_user_0010() returns setof text as $$ -- - , - -- runtests(). -- , : declare v_user_id integer; begin -- - , , : return next lives_ok('select test_user.add_user(''testuser unique''::varchar);', 'test_user.add_user doesnt throw exception'); -- , , , (>0): v_user_id := test_user.add_user('blah blah'); return next cmp_ok(v_user_id, '>', 0, 'test_user.add_user: returns ok'); --, . return next results_eq('select user_name::varchar from test_user.users where user_id=' || v_user_id::varchar, 'select ''blah blah''::varchar', 'test_user.add_user inserts ok'); -- : return next is(test_user.alter_user(v_user_id,'new user name blah'), v_user_id, 'test_user.alter_user: returns ok'); --, : return next results_eq('select user_name::varchar from test_user.users where user_id=' || v_user_id::varchar, 'select ''new user name blah''::varchar', 'test_user.alter_user updates record'); -- id: return next is(test_user.delete_user(v_user_id), v_user_id, 'test_user.delete_user: returns ok'); -- . , : return next is_empty('select 1 from test_user.users where user_id=' || v_user_id::varchar, 'test_user.delete_user: deletes ok'); end; $$ language plpgsql;
SQLからテストを直接実行できます。
psql -h $db_host -p $db_port -U $db_user $db_name -f tests/run_user.sql
この場合、出力で純粋なTAPを取得します。
計画| 1..10
test_user_0010 | ok 1-test_user.add_userは例外をスローしません
test_user_0010 | ok 2-test_user.add_user:okを返します
test_user_0010 | ok 3-test_user.add_userがレコードを挿入します
test_user_0010 | ok 4-test_user.alter_user:okを返します
test_user_0010 | ok 5-test_user.alter_userはレコードを更新します
test_user_0010 | ok 6-test_user.delete_user:okを返します
test_user_0010 | ok 7-test_user.delete_user:okを削除
tables_are | ok 8-スキーマtest_userにはusersテーブルが含まれます
columns_are | ok 9-test_user.users列チェック
test_scheme_check_func | ok 10-スキーマtest_userのすべての関数はテストでカバーされています。
または、pg_proveユーティリティを使用します。
pg_prove -h $db_host -p $db_port -d $db_name -U $db_user tests/run_*.sql
その場合、出力はより人間に読みやすいものになります。
tests / run_user.sql .. ok
すべてのテストが成功しました。
ファイル= 1、テスト= 10、0ウォールクロック秒(0.04 usr + 0.00 sys = 0.04 CPU)
結果:合格
pg_skeletonでは、ホスト、ポート、ユーザー名、およびデータベースの変数は、スクリプト/test/run_tests.shに置き換えられます
PostgreSQLのストアドファンクションのコードを持っているすべての人が単体テストを受けることを望んでいます!