すべてのプロダクト
Search
ドキュメントセンター

PolarDB:pgtap

最終更新日:Nov 11, 2024

pgTAP拡張機能は、PL/pgSQLおよびPL/SQLで記述されたユニットテストフレームワークです。 PolarDB for PostgreSQL のTAPテストフレームワークとして、TAP発行アサーション関数の包括的なコレクションと、他のTAP発行テストフレームワークと統合する機能が含まれています。

前提条件

拡張機能は、次のエンジンを実行するPolarDB for PostgreSQLクラスターでサポートされています。

  • PostgreSQL 14 (バージョン14.5.3.0以降)

  • PostgreSQL 11 (バージョン1.1.30以降)

説明

次のいずれかのステートメントを実行して、PolarDB for PostgreSQLクラスターのリビジョンバージョンを表示できます。

  • PostgreSQL 14

    SELECT version();
  • PostgreSQL 11

    SHOW polar_version;

用語

  • 単体テスト: システムのさまざまなモジュールの正確さをテストできます。 モジュールテストとも呼ばれます。

  • Test anything protocol (TAP): 言語の独立性を維持し、テスト中のエラー報告を簡素化しながら、テスト結果をテストハーネスに通信するためのメカニズムを提供します。 もともとはPerl言語用に開発されました。

使用状況

説明

pgTAP拡張機能を作成するには、スーパーユーザーの権限が必要です。お問い合わせください。

  • エクステンションを作成します。

    CREATE EXTENSION pgtap;
  • エクステンションを削除します。

    DROP EXTENSION pgtap;

テスト例

pgTAP拡張機能は、テーブルスペース、スキーマ、テーブル、列、ビュー、シーケンス、インデックス、トリガー、関数、ポリシー、ユーザー、言語、ルール、クラス、演算子、および拡張機能のための幅広いテストメソッドを提供します。

次の例は、テーブル、ポリシー、列、および関数にpgTAP拡張機能を使用する方法を示しています。

  • テーブル、インデックス、またはビューのテスト

    テーブル、インデックス、およびビューが存在するかどうかを確認するには、次のサンプルスクリプトを使用します。

    BEGIN;
    SELECT plan(6);
    
    -- Check whether the tap_table table exists.
    SELECT has_table('tap_table');
    
    -- Check whether the tap_table_non_exist table does not exist.
    SELECT hasnt_table('tap_table_non_exist');
    
    -- Check whether the tap_view view exists.
    SELECT has_view('tap_view');
    
    -- Check whether the materialized_tap_view materialized view exists.
    SELECT has_materialized_view('materialized_tap_view');
    
    -- Check whether the tap_table table has the tap_table_index index.
    SELECT has_index('tap_table', 'tap_table_index');
    
    -- Check whether tap_table is a relation.
    SELECT has_relation('tap_table');
    
    SELECT * FROM finish();
    ROLLBACK;
    説明
    • has_tablehasnt_tableは、指定されたテーブルが存在するかどうかを確認するために使用されます。

    • has_viewは、指定されたビューが存在するかどうかを確認します。

    • has_materialized_viewは、指定されたマテリアライズドビューが存在するかどうかを確認します。

    • has_indexは、テーブルに指定されたインデックスがあるかどうかを確認するために使用されます。

    • has_relationは、指定されたリレーション (テーブル、インデックス、またはシーケンス) が存在するかどうかを確認するために使用されます。

    上記のスクリプトの次のサンプルの結果は、テーブルやインデックスなどの指定されたオブジェクトが存在しないことを示しています。

                        has_table
    -------------------------------------------------
     not ok 1 - Table tap_table should exist        +
     # Failed test 1: "Table tap_table should exist"
    (1 row)
                        hasnt_table
    ---------------------------------------------------
     ok 2 - Table tap_table_non_exist should not exist
    (1 row)
                       has_view
    -----------------------------------------------
     not ok 3 - View tap_view should exist        +
     # Failed test 3: "View tap_view should exist"
    (1 row)
                              has_materialized_view
    -------------------------------------------------------------------------
     not ok 4 - Materialized view materialized_tap_view should exist        +
     # Failed test 4: "Materialized view materialized_tap_view should exist"
    (1 row)
                           has_index
    -------------------------------------------------------
     not ok 5 - Index tap_table_index should exist        +
     # Failed test 5: "Index tap_table_index should exist"
    (1 row)
                        has_relation
    ----------------------------------------------------
     not ok 6 - Relation tap_table should exist        +
     # Failed test 6: "Relation tap_table should exist"
    (1 row)
                    finish
    --------------------------------------
     # Looks like you failed 5 tests of 6
    (1 row)

    次のステートメントを実行して、テーブル、インデックス、およびビューを作成します。

    CREATE TABLE tap_table(col INT PRIMARY KEY, tap_desc TEXT);
    CREATE INDEX tap_table_index on tap_table(col);
    CREATE VIEW tap_view AS SELECT * FROM tap_table;
    CREATE MATERIALIZED VIEW materialized_tap_view AS SELECT * FROM tap_table;

    テーブル、インデックス、およびビューが作成されたら、前述のTAPテストを再度実行します。 次のサンプル結果が表示されます。

                 has_table
    -------------------------------------
     ok 1 - Table tap_table should exist
    (1 row)
                        hasnt_table
    ---------------------------------------------------
     ok 2 - Table tap_table_non_exist should not exist
    (1 row)
                 has_view
    -----------------------------------
     ok 3 - View tap_view should exist
    (1 row)
                        has_materialized_view
    -------------------------------------------------------------
     ok 4 - Materialized view materialized_tap_view should exist
    (1 row)
                     has_index
    -------------------------------------------
     ok 5 - Index tap_table_index should exist
    (1 row)
                  has_relation
    ----------------------------------------
     ok 6 - Relation tap_table should exist
    (1 row)
     finish
    --------
    (0 rows)
  • RLSポリシーテスト

    行レベルセキュリティ (RSL) ポリシーがテーブルに存在するかどうかを確認するには、次のサンプルスクリプトを使用します。

    CREATE USER tap_user_1;
    CREATE USER tap_user_2;
    CREATE TABLE tap_table(col INT PRIMARY KEY, tap_desc TEXT);
    CREATE POLICY tap_policy ON tap_table FOR select TO tap_user_1, tap_user_2;
    
    BEGIN;
    SELECT plan(5);
    SELECT policy_cmd_is(
        'public',
        'tap_table',
        'tap_policy'::NAME,
        'select'
    );
    SELECT policy_roles_are(
      'public',
      'tap_table',
      'tap_policy',
      ARRAY [
        'tab_user_1', -- Check whether the tab_user_1 user is restricted by the RLS policy tab_policy.
        'tab_user_2' -- Check whether thetab_user_2 user is restricted by the RLS policy tab_policy.
      ]
    );
    SELECT policies_are(
      'public',
      'tap_table',
      ARRAY [
        'TAP_POLICE' -- Check whether the tap_policy table contains the RLS policy tab_policy.
      ]
    );
    SELECT * FROM check_test(
        policy_roles_are(
          'public',
          'tap_table',
          'tap_policy',
          ARRAY [
            'tape_user_1' -- Check whether the tab_user_1 user is the only user restricted by the RLS policy tab_policy.
          ]),
        false,
        'check policy roles',
        'Policy tap_policy for table public.tap_table should have the correct roles');
    SELECT * FROM finish();
    ROLLBACK;
    
    DROP POLICY tap_policy ON tap_table;
    DROP TABLE tap_table;
    DROP USER tap_user_1;
    DROP USER tap_user_2;
    説明
    • policy_cmd_は、指定されたRLSポリシーの存在を確認するために使用されます。

    • policy_roles_ は、RLSポリシーがすべてのユーザーに適用されるかどうかを確認するために使用されます。 RLSポリシーが適用されるすべてのユーザーが指定されている場合に限り、関数はTRUEを返します。

    • policies_ は、テーブルにRLSポリシーが含まれているかどうかを確認するために使用されます。

    予想されるエラー結果をテストするには、check_testメソッドを使用して、予想される結果をTRUEまたはFALSEとして指定します。 サンプル結果:

                                       policy_cmd_is
    ------------------------------------------------------------------------------------
     ok 1 - Policy tap_policy for table public.tap_table should apply to SELECT command
    (1 row)
                                     policy_roles_are
    -----------------------------------------------------------------------------------
     ok 2 - Policy tap_policy for table public.tap_table should have the correct roles
    (1 row)
                              policies_are
    ----------------------------------------------------------------
     ok 3 - Table public.tap_table should have the correct policies
    (1 row)
                              check_test
    --------------------------------------------------------------
     ok 4 - check policy roles should fail
     ok 5 - check policy roles should have the proper description
    (2 rows)
     finish
    --------
    (0 rows)
  • 列テスト

    テーブル内の列が存在するかどうか、およびその列が主キーか外部キーかを確認するには、次のサンプルスクリプトを使用します。

    CREATE TABLE tap_table(col INT PRIMARY KEY, tap_desc TEXT);
    CREATE INDEX tap_table_index ON tap_table(col);
    CREATE UNIQUE INDEX tap_table_unique_index ON tap_table(col);
    
    BEGIN;
    SELECT plan(7);
    -- Check whether the col column is the primary key of the tap_table table.
    SELECT col_is_pk('tap_table', 'col');
    -- Check whether the tap_desc column is not a primary key of the tap_table table.
    SELECT col_isnt_pk('tap_table', 'tap_desc');
    -- Check whether the col column is a foreign key of the tap_table table.
    SELECT * FROM check_test(
        col_is_fk('tap_table', 'col'),
        false,
        'check foreign key of table',
        'Column tap_table(col) should be a foreign key');
    -- Check whether the col column is not a foreign key of the tap_table table.
    SELECT col_isnt_fk('tap_table', 'col');
    -- Check whether the tap_table table contains the col column.
    SELECT has_column('tap_table', 'col');
    -- Check whether the tap_table table does not contain the col column.
    SELECT hasnt_column('tap_table', 'non_col');
    SELECT * FROM finish();
    ROLLBACK;
    
    DROP TABLE tap_table;
    説明
    • col_is_pkは、列がテーブルの主キー列であるかどうかを確認するために使用されます。

    • col_isnt_pkは、列がテーブルの主キーでないかどうかを確認するために使用されます。

    • col_isnt_fkは、列がテーブルの外部キーでないかどうかを確認するために使用されます。

    • has_columnは、テーブルに列が含まれているかどうかを確認するために使用されます。

    • hasnt_columnは、テーブルに列が含まれていないかどうかを確認するために使用されます。

    サンプル結果:

                          col_is_pk
    ------------------------------------------------------
     ok 1 - Column tap_table(col) should be a primary key
    (1 row)
                              col_isnt_pk
    ---------------------------------------------------------------
     ok 2 - Column tap_table(tap_desc) should not be a primary key
    (1 row)
                                  check_test
    ----------------------------------------------------------------------
     ok 3 - check foreign key of table should fail
     ok 4 - check foreign key of table should have the proper description
    (2 rows)
                           col_isnt_fk
    ----------------------------------------------------------
     ok 5 - Column tap_table(col) should not be a foreign key
    (1 row)
                    has_column
    ------------------------------------------
     ok 6 - Column tap_table.col should exist
    (1 row)
                       hasnt_column
    --------------------------------------------------
     ok 7 - Column tap_table.non_col should not exist
    (1 row)
     finish
    --------
    (0 rows)
  • 関数テスト

    関数の戻り値の型と、関数がSECURITY DEFINERであるかどうかを確認するには、次のサンプルスクリプトを使用します。

    CREATE OR REPLACE FUNCTION tap_function()
    RETURNS text
    AS $$
    BEGIN
        RETURN 'This is tap test function';
    END;
    $$ LANGUAGE plpgsql SECURITY DEFINER;
    
    CREATE OR REPLACE FUNCTION tap_function_bool(arg1 integer, arg2 boolean, arg3 text)
    RETURNS boolean
    AS $$
    BEGIN
        RETURN true;
    END;
    $$ LANGUAGE plpgsql;
    
    BEGIN;
    SELECT plan(6);
    -- Check whether the return value type of the tap_function function is TEXT.
    SELECT function_returns('tap_function', 'text');
    -- Check whether the return value type of the tap_function_bool function whose parameter list is INTEGER, BOOLEAN, and TEXT is BOOLEAN.
    SELECT function_returns('tap_function_bool', ARRAY['integer', 'boolean', 'text'], 'boolean');
    -- Check whether the tap_function function is SECURITY DEFINER.
    SELECT is_definer('tap_function');
    -- Check whether the tap_function_bool function is not SECURITY DEFINER.
    SELECT isnt_definer('tap_function_bool');
    -- Check whether the tap_function_bool function is SECURITY DEFINER.
    SELECT * FROM check_test(
        is_definer('tap_function_bool'),
        false,
        'check function security definer',
        'Function tap_function_bool() should be security definer');
    SELECT * FROM finish();
    ROLLBACK;
    
    DROP FUNCTION tap_function;
    DROP FUNCTION tap_function_bool;
    説明
    • function_returnsは、関数の戻り値型が指定された型であるかどうかを確認したり、関数のパラメーターリストを指定したりするために使用されます。

    • is_definerは、指定された関数がSECURITY definerであるかどうかを確認するために使用されます。

    • isnt_definerは、指定された関数がSECURITY definerでないかどうかを検出するために使用されます。

    サンプル結果:

     function_returns
    ---------------------------------------------------
     ok 1 - Function tap_function() should return text
    (1 row)
                                    function_returns
    ---------------------------------------------------------------------------------
     ok 2 - Function tap_function_bool(integer, boolean, text) should return boolean
    (1 row)
                            is_definer
    -----------------------------------------------------------
     ok 3 - Function tap_function() should be security definer
    (1 row)
                                isnt_definer
    --------------------------------------------------------------------
     ok 4 - Function tap_function_bool() should not be security definer
    (1 row)
                                    check_test
    ---------------------------------------------------------------------------
     ok 5 - check function security definer should fail
     ok 6 - check function security definer should have the proper description
    (2 rows)
     finish
    --------
    (0 rows)
  • その他のテスト

    pgTAP拡張機能は、前述のテストに加えて他のテスト方法を提供します。 テスト項目は異なりますが、全体的な使用法は前の例と同じです。 詳細については、「pgTAPドキュメント」をご参照ください。