DEV Community

Cover image for ApidogでAPIテストにデータベースクエリを活用する方法 (MySQL, MongoDB, Redis)
Akira
Akira

Posted on • Originally published at apidog.com

ApidogでAPIテストにデータベースクエリを活用する方法 (MySQL, MongoDB, Redis)

緑色のステータスコードだけでは、APIの正しさを証明できません。たとえば POST /orders201 Created を返し、レスポンスボディも期待どおりでも、注文行が正しい状態でデータベースに保存されたとは限りません。在庫数が減っているか、外部キーが正しく設定されているか、ソフトデリートが意図せずハードデリートになっていないかは、HTTPレスポンスだけでは確認できません。APIテストで「システムが返した内容」だけでなく「実際に永続化した内容」まで検証するには、テストシナリオからデータベースを直接クエリします。

今すぐApidogを試す

テストでは、リクエスト前に既知の状態をシードし、APIを実行し、リクエスト後にテーブルをクエリして結果を確認します。Apidogでは、データベース接続とデータベース操作プロセッサーを使い、外部スクリプトなしでSQLまたはNoSQLコマンドをシナリオのステップとして実行できます。シナリオ作成の基本は、Apidogでテストシナリオを作成する方法を参照してください。リレーショナルデータの基本を復習したい場合は、MDNのサーバーサイド概要も役立ちます。

テストにおけるデータベース操作の利点

データベースに触れないAPIテストは、基本的にブラックボックステストです。レスポンスを確認するには十分ですが、APIの返却値と永続化データの間にある不整合は検出できません。

データベース操作ステップを追加すると、次の3つを実現できます。

  • シード: テスト開始前に必要なデータを作成し、残存データへの依存をなくす
  • 永続化の検証: APIが作成・更新したはずの行を直接確認する
  • 実値の抽出: DBで生成・保持された値を後続リクエストへ渡す

Apidogでは、まず 設定 > データベース接続 で接続を作成します。その後、リクエストの前に実行するプリプロセッサー、または後に実行するポストプロセッサーとしてデータベース操作を追加します。作成した接続はプロジェクト内の複数シナリオで再利用できます。

利用可能なデータベースにはプラン上の違いがあります。

データベース 利用条件
MySQL 無料プラン
SQL Server(2014以降) 無料プラン
PostgreSQL 無料プラン
Oracle 無料プラン
ClickHouse 有料プラン
MongoDB 有料プラン
Redis 有料プラン

以降のMySQLの例は無料プランで実行できます。MongoDBとRedisを使う場合は有料プランが必要です。

ステップ1: データベース接続を作成する

  1. 設定 > データベース接続 を開きます。
  2. 右上の + 新規 をクリックします。
  3. データベース種別を選択します。
  4. 接続情報を入力して保存します。

主な入力項目は次のとおりです。

  • ホスト: db.staging.internal または 127.0.0.1
  • ポート: MySQLなら 3306
  • ユーザー名
  • パスワード
  • データベース名: 例 shop

データベース接続設定画面

踏み台サーバー経由で接続する場合は、SSHトンネルを展開してジャンプホストの情報を設定します。

MySQLではSSLモードも選択できます。

  • Prefer: SSLを試行し、失敗時にフォールバックするデフォルト設定
  • Require
  • Verify CA
  • Verify Full

可能であれば、サーバーが対応する最も厳格なモードを選択してください。

MySQL 8で認証エラーが出る場合

MySQL 8では、デフォルトの caching_sha2_password 認証プラグインにより接続できない場合があります。認証エラーが発生する場合は、テスト用ユーザーの認証方式を変更して再接続します。

ALTER USER 'tester'@'%'
IDENTIFIED WITH mysql_native_password BY '...';
Enter fullscreen mode Exit fullscreen mode

認証プラグインの違いは、MySQLリファレンスマニュアルで確認できます。

データベース接続の認証情報はローカルマシンに保存され、クラウドへ同期されません。チームメンバーごとに接続を設定してください。チームでの運用方法は、データベース接続設定の共有も参照してください。

ステップ2: プリプロセッサーでデータをシードする

注文作成APIをテストする場合、リクエスト前に既知の顧客を作成しておくと、既存データやテスト実行順に依存しないテストになります。

リクエストを開き、次の手順でデータベース操作を追加します。

  1. プリプロセッサーを開く
  2. データベースプロセッサーを追加
  3. データベース操作を選択
  4. 操作名を seed customer に設定
  5. MySQL接続を選択
  6. SQLコマンドを入力にSQLを記述

環境変数などの動的な値は {{variable_name}} 形式で参照できます。

INSERT INTO customers (id, email, status)
VALUES ({{customer_id}}, '{{customer_email}}', 'active')
ON DUPLICATE KEY UPDATE status = 'active';
Enter fullscreen mode Exit fullscreen mode

このSQLにより、テスト開始時に次の状態を保証できます。

  • 顧客が存在する
  • 顧客のステータスが active である
  • 顧客IDが後続ステップで利用できる

テストを自己完結させるため、シード処理はプリプロセッサーに置くのが基本です。

ステップ3: ポストプロセッサーでデータベースをアサートする

次に、APIが作成した注文が実際に orders テーブルへ保存されたことを確認します。

まず、注文作成APIを呼び出します。

POST /api/orders
Content-Type: application/json

{
  "customer_id": {{customer_id}},
  "items": [{ "sku": "APRON-01", "qty": 2 }]
}
Enter fullscreen mode Exit fullscreen mode

レスポンスに注文IDが含まれる場合は、通常のレスポンスアサーションで order_id として保存します。

続けて、同じリクエストにポストプロセッサーを追加します。

  1. ポストプロセッサーを追加を選択
  2. データベース操作を選択
  3. 操作名を verify order row に設定
  4. 接続を選択
  5. 次のSQLを設定
SELECT id, status, total_cents
FROM orders
WHERE id = {{order_id}};
Enter fullscreen mode Exit fullscreen mode

クエリ結果は、行ごとのオブジェクト配列として返されます。最初の行の status を変数へ保存するには、結果を抽出(オプション)結果を変数に抽出を追加します。

  • 変数名: db_order_status
  • JSONPath式:
$[0].status
Enter fullscreen mode Exit fullscreen mode

実行後、コンソールで生のクエリ結果と抽出値を確認してください。そのうえで、db_order_status が期待する pending などの値と一致するアサーションを追加します。

これにより、以下のような不具合を検出できます。

  • APIは 201 Created を返した
  • しかしDBでは status = 'draft' になっていた
  • レスポンスでは正常に見えるが、永続化処理が不正だった

ステップ4: データベース値を抽出して後続リクエストで使う

データベースからの値抽出は、アサーションだけに使うものではありません。APIレスポンスには含まれない内部生成値を、後続のリクエストで使うケースがあります。

たとえば注文作成時に fulfillment_ref がDB上で生成される一方、APIレスポンスには含まれないとします。後続のエンドポイントがこの値を要求する場合、ポストプロセッサーで取得できます。

SELECT fulfillment_ref
FROM orders
WHERE id = {{order_id}};
Enter fullscreen mode Exit fullscreen mode

抽出設定は次のとおりです。

  • 変数名: fulfillment_ref
  • JSONPath式:
$[0].fulfillment_ref
Enter fullscreen mode Exit fullscreen mode

後続リクエストでは、URLやリクエストボディで {{fulfillment_ref}} を参照します。

GET /api/fulfillments/{{fulfillment_ref}}
Enter fullscreen mode Exit fullscreen mode

HTTPレスポンスから値を渡すのと同じ考え方ですが、値の取得元がJSONレスポンスではなくデータベースです。関連するパターンは、テストステップ間でデータを渡すおよびAPIテストのオーケストレーションとデータ受け渡しでも確認できます。

MongoDBとRedis: NoSQLのバリアント

MongoDBとRedisでもデータベース操作プロセッサーを利用できます。ただし、どちらも有料機能です。詳細なフィールド仕様はApidogドキュメントを確認してください。

MongoDB

MongoDBでは、生SQLの代わりに操作タイプを選択します。

  • Find
  • Insert
  • Update
  • Delete
  • データベースコマンドの実行

CRUD操作ではコレクション名が必要です。クエリ条件にはJSONを入力します。

{ "_id": "65486728456e79993a150f1c" }
Enter fullscreen mode Exit fullscreen mode

一致するID文字列は自動的に ObjectId として処理されます。BSON型が必要な場合は、次のヘルパーも利用できます。

  • ISODate(...)
  • ObjectId(...)
  • NumberDecimal(...)
  • NumberLong(...)

各型の詳細はMongoDBマニュアルを参照してください。

なお、MySQLのようなJSONPathベースの変数抽出については、MongoDBとRedisのドキュメントでは同じ仕組みが明示されていません。まずは状態のシードと確認を中心に使い、抽出が必要な場合はコンソールで動作を確認してください。

Redis

Redis接続では、次の情報を入力します。

  • ホスト
  • ポート
  • パスワード
  • データベースインデックス

ビジュアル操作では、次の操作タイプを利用できます。

  • GET
  • SET
  • DELETE

たとえばキャッシュされたセッションを確認する場合、GETを選択し、キーを次のように指定します。

user:session:123
Enter fullscreen mode Exit fullscreen mode

ドロップダウンにない操作は、Redisコマンドの実行タブで実行できます。

KEYS user:*
Enter fullscreen mode Exit fullscreen mode

これにより、APIが書き込むべきキャッシュエントリの確認や、テスト前のキャッシュクリアが可能です。

高度なバリエーションと制限事項

大きなテストスイートを作る前に、以下のポイントを確認してください。

  • ループ

    ForEachステップで行を反復する場合、現在の要素は {{$.StepID.element.field}} で参照できます。StepID はループステップの実際の番号です。

  • DB値による分岐

    ステータスを抽出し、paidpending で後続の処理を分岐できます。APIテストシナリオにおける条件ロジックと組み合わせると、DB状態に応じたシナリオを作成できます。

  • 環境ごとの接続切り替え

    環境ごとに接続を作成しておくと、選択中の環境に対応するDBへ自動的にルーティングされます。

  • ストアドプロシージャ

    ビジュアルインターフェースでは、ストアドプロシージャのような複雑な操作は対象外です。SQLは単純な SELECTINSERTUPDATEDELETE に留めてください。

  • Oracleのセットアップ

    Oracleへ接続するには、事前にローカルマシンへOracle Clientをインストールする必要があります。

環境ごとの認証情報を管理する

テストが誤って本番データへ接続しないよう、環境ごとにデータベース接続を作成します。

たとえば、以下のように分けます。

  • local: ローカル開発DB
  • staging: ステージングDB

各接続には、それぞれのホスト・ユーザー・パスワードを設定します。その後、画面右上の環境ドロップダウンで環境を切り替えます。

  • staging を選択すると、シナリオ内のクエリはステージングDBで実行される
  • local を選択すると、同じSQLがローカルDBで実行される

SQLやテストステップを書き換える必要はありません。

認証情報はローカルに保存されるため、共有クラウドプロジェクトに本番パスワードが同期されることもありません。各エンジニアが自身の認証情報を管理できます。

Apidog CLIでワークフローを自動化する

アプリ上でシナリオが通ったら、CIでも実行してプルリクエストごとにDBアサーションを検証します。

まず、CLIをインストールして認証します。

npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
Enter fullscreen mode Exit fullscreen mode

次に、シナリオIDと環境IDを指定して実行します。

apidog run --access-token $APIDOG_ACCESS_TOKEN -t <scenario_id> -e <env_id> -r cli
Enter fullscreen mode Exit fullscreen mode

主なオプションは次のとおりです。

オプション 内容
-t テストシナリオID
-e 環境ID
-r レポーター

レポーターには clihtmljunit を指定できます。複数指定する場合はカンマ区切りです。

apidog run --access-token $APIDOG_ACCESS_TOKEN \
  -t <scenario_id> \
  -e <env_id> \
  -r html,cli
Enter fullscreen mode Exit fullscreen mode

データベース接続情報はローカルに保存されるため、CIからDBへ接続するには、ランナーに必要な設定を用意する必要があります。データセットの各行で同じDBアサーションを実行する場合は、Apidog CLIによるデータ駆動型テストを参照してください。定期実行は、ApidogによるAPIテストのスケジュール設定で設定できます。

よくある質問

無料で使えるデータベースと有料のデータベースはどれですか?

MySQL、SQL Server(2014以降)、PostgreSQL、Oracleは無料プランで利用できます。ClickHouse、MongoDB、Redisは有料プランが必要です。

データベースの値を後続リクエストで使えますか?

はい。ポストプロセッサーで SELECT を実行し、結果を変数に抽出を使います。たとえば、次のJSONPathで最初の行の値を抽出できます。

$[0].fulfillment_ref
Enter fullscreen mode Exit fullscreen mode

抽出後は {{fulfillment_ref}} のように参照します。

チームメイトは自動的にデータベース接続を取得できますか?

いいえ。接続の認証情報はクライアントごとにローカル保存され、クラウドには同期されません。各メンバーが個別に設定します。

MySQL 8への接続が失敗するのはなぜですか?

MySQL 8のデフォルト認証プラグイン caching_sha2_password が原因の場合があります。必要に応じて、ユーザーを mysql_native_password へ切り替えて再接続してください。

ALTER USER 'tester'@'%'
IDENTIFIED WITH mysql_native_password BY '...';
Enter fullscreen mode Exit fullscreen mode

ストアドプロシージャや複雑なDBロジックを実行できますか?

ビジュアルインターフェースでは対応していません。テストステップでは、標準的な SELECTINSERTUPDATEDELETE のような直接的なステートメントを使ってください。

まとめ

データベースクエリを組み込むと、APIテストを「レスポンスが正しく見える」状態から「データが実際に正しい」状態へ進められます。

実装の基本パターンは次のとおりです。

  1. プリプロセッサーでテストデータをシードする
  2. APIリクエストを実行する
  3. ポストプロセッサーでDBの行をクエリする
  4. 永続化された値をアサートする
  5. 必要ならDB値を変数へ抽出し、後続リクエストへ渡す

環境ごとに接続を分ければ、同じシナリオをローカル環境とステージング環境で安全に使い回せます。

まずはApidogをダウンロードし、開発用MySQLへ接続してみてください。次に、APIリクエストが作成した行を確認するポストプロセッサーを1つ追加すると、HTTPレスポンスだけでは見えない不具合を検出できます。

Top comments (0)