API自動テストツールTavernにおけるリクエストパラメータの動的生成

こんにちは。SHIFTのテスト自動化エンジニアの松岡です。

Tavernは、yamlに期待値を記載するだけで、APIのレスポンスJSONのアサーションを行うことができるテストツールです。

以前の記事ではレスポンスに対するアサーションのカスタマイズ方法をご紹介致しました。 今回は試験対象APIを呼び出す前に、リクエストを動的に生成する(実行時ごとに設定する)方法をご紹介致します。

ここでは外部関数をpythonで定義して、リクエストパラメータ(年月)を実行時ごとに生成する実装を行っていきたいと思います。


◆ディレクトリ構成

※以前の記事でも紹介しましたが、繰り返します。

testFolderhelper
 │   └ testing_utils.py …… 外部関数を記述するpythonです
 └ test
     ├ __init__.py …… yamlからpythonを呼ぶために必要なファイル。
     └ test_foo_bar.tavern.yaml …… テストケース

yamlと同じ階層に「__init__.py」を配置します。そうすることで、テスト実行時に、yamlを格納しているディレクトリの親ディレクトリから配下のディレクトリを参照してpythonを呼び出すことができます。(__init__.pyの役割とpythonの呼び出しについてはここでは割愛します。)

◆処理実装

例として、以下のようなパスパラメータが必須となるAPIを対象に、実装の仕方を説明します。

URL:test_host/get/{yyyyMM}
HTTPメソッド:GET
パスパラメータ:yyyyMM(年月)
認証:アクセストークン

¶ test_foo_bar.tavern.yaml

stages:
  - name: Setup Get Access Token
    request:
      url: "https://apitest/token"
      method: POST
      headers:
         Accept: "application/json"
         client_id: "foo"
         client_secret: "bar"
         code: "hoge"
    response:
      strict: false
      status_code: 200
      json:
         access_token: !anything
      save:
         $ext: ……※1
            function: helper.testing_utils:generate_request_yyyymm ……※1
         json:
            test_token: access_token ……※2

外部関数を使用したアサーションではresponseのブロックにて、「verify_response_with」を記載していましたが、リクエストの値を生成するにはresponse>saveのブロックに「$ext」を記載します(※1)。 ここではテスト対象のAPIにアクセスする前準備としてaccess_tokenを 取得するAPIを実行して、レスポンスJSONの「access_token」を変数「test_token」に格納していますが、外部関数で生成した値の変数への格納は記述していません(※2)。

外部関数で生成した値は、変数への格納も外部関数で行うようにします。

¶ testing_utils.py

from datetime import datetime as dt ……※1
from datetime import timedelta as delta ……※1
from box import Box ……※1

JST_DIFF = 9 ……※2

def generate_request_yyyymm(response):
    current_time_obj = dt.utcnow() + delta(hours=JST_DIFF) ……※2
    yyyymm = current_time_obj.strftime('%Y%m') ……※3
    return Box({'test_yyyymm': yyyymm}) ……※4

python全体は以上のようになります。 まず日付を扱うために必要なモジュールとtavernに変数として返すためのBoxというモジュールをインポートしておきます(※1)。 関数内ではまず、現在時刻(システム日付)を表すオブジェクトを生成します。デフォルトではUTCとなります。この例ではJSTにするために定数に格納した9時間分を加算しています(※2)。

次に、現在時刻のオブジェクトから日付の文字列を生成します。strftimeに引数を渡すことで日付の書式を定義できます。ここでは年月(yyyyMM)を指定しています(※3)。 最後に、生成した文字列を格納した変数と、tavernのyamlから参照する際の変数名(ここでは"test_yyyymm")をペアの連想配列にして、Boxで返却しています(※4)。

これでこの変数の呼出し以降、「test_yyyymm」という変数名で年月を使用することができるようになりました。  

次のテストステップは以下のようになります。

¶ test_foo_bar.tavern.yaml

  - name: Get Data
    request:
      url: "https://test_host/get/{test_yyyymm}" ……※1
      method: GET
      headers:
         Authorization: "bearer {test_token}" ……※2
    response:
      strict: false
      status_code: 200
      json:
         hoge: "fuga" ……※3

urlのパスパラメータに「test_yyyymm」という変数を使用しています(※1)。 1つ前のステップのresponseブロックでは定義されていませんが、呼び出したpython内で返却しているため、この変数名が使用可能になります。 また、前のステップで取得したaccess tokenを認証に使用しています(※2)。 必要に応じてレスポンスのアサーションを追加します(※3)。  

まとめ

動的にリクエストパラメータの値を変える必要がある場合、pythonに外部関数を記述することで実装することができます。 なお今回の例では、外部関数で生成した変数名をパスパラメータに使用しましたが、リクエストBodyに変数を指定することもできます。  

Appendix:サンプルコード

¶ test_foo_bar.tavern.yaml

test_name: Set Request Parameter Sample

stages:
  - name: Setup Get Access Token
    request:
      url: "https://apitest/token"
      method: POST
      headers:
         Accept: "application/json"
         client_id: "foo"
         client_secret: "bar"
         code: "hoge"
    response:
      strict: false
      status_code: 200
      json:
         access_token: !anything
      save:
         $ext:
            function: helper.testing_utils:generate_request_yyyymm
         json:
            test_token: access_token

  - name: Get Data
    request:
      url: "https://test_host/get/{test_yyyymm}"
      method: GET
      headers:
         Authorization: "bearer {test_token}"
    response:
      strict: false
      status_code: 200
      json:
         hoge: "fuga"

¶ testing_utils.py

from datetime import datetime as dt
from datetime import timedelta as delta
from box import Box

JST_DIFF = 9

def generate_request_yyyymm(response):
    current_time_obj = dt.utcnow() + delta(hours=JST_DIFF)
    yyyymm = current_time_obj.strftime('%Y%m')
    return Box({'test_yyyymm': yyyymm})

※ エディタの都合上インデントがずれてしまう場合があります。コピペ時にお手元でご確認ください。

【この公式ライターのほかの記事も読む】

API自動テスト_レスポンスアサーションのコーディングルール化のすすめ
API自動テストツールTavernによるレスポンス配列のアサーション

_________________________________

執筆者プロフィール:松岡 直人                    SIerでのJava、jqueryの開発経験を経て、SHIFTに入社。 SHIFTでは入社当初より画面/APIテスト自動化に関わる。 「人間が最低限しか頑張らない自動化」を目指している。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら 
https://recruit.shiftinc.jp/career/