Apache JMeter でクラウド・ベースのアプリケーションをテストする

JMeter で RESTful な API をテストする効果的手法とベスト・プラクティスを学ぶ

JMeter は、クラウド内で実行されるアプリケーションをテストするために利用できる強力なテスト・ツールですが、JMeter の効果的な使用方法を知らなければ、JMeter のスクリプトを管理して保守するのに手こずる可能性があります。この記事では、適切に設計された自動 JMeter タスクをクラウド・ベースのアプリケーションのテストに実装する際に役立つ手法を紹介します。

Shalini Gilra, Automation Lead, IBM

Author photoShalini Gilra は、プネにある IBM India Software Labs に勤務し、SmarterCloud プラットフォームの自動化に携わる開発者です。機能テストと REST API テストを対象とした Rational Functional Tester、Selenium、JMeter、JUnit, STAF/STAX、および Perl でのテストの自動化で 12 年の経験を積んでいます。developerWorks の記事「Incorporating external features in IBM Rational Functional Tester」も執筆している彼女は、Sun 認定 Java プログラマーであり、WebSphere Portal Server の認定も保有しています。



Prem Prakash, Software Test Specialist, IBM

Author photoPrem Prakash は、プネにある IBM India Software Labs に勤務する、SmarterCloud プラットフォームのソフトウェア・テスト・スペシャリストです。IT の世界で 12 年の経験を持ち、サーバー・サイドのテスト、シェルおよび Perl のスクリプト作成、データベース・テストに携わってきました。



Tom Tuohy, Automation Developer, IBM

Author photoTom Tuohy は、IBM Littleton, Massachusetts Labs に勤務し、SmarterCloud プラットフォームの自動化に携わる開発者です。IBM に勤務する間、Lotus Notes/Domino、Lotus Quickplace/Quickr、Lotus Connections、および Sterling Commerce の自動化フレームワークを設計および作成し、貢献してきました。C、C++、Java で作成された API、Web サービス、およびエンタープライズ・アプリケーションのバックエンド・テストを専門に 20 年以上の経験を積んできました。



2013年 10月 10日

クラウド・ベースのアプリケーションには一般に、XML 形式または JSON (JavaScript Object Notation) 形式のデータを交換する API によってやりとりする複数のコンポーネントが関与します。この記事では、RESTful な Web API と JSON を使用するクラウド対応のアプリケーションの機能テスト、パフォーマンス・テスト、および信頼性テストを Apache JMeter ― GUI ベースでオープンソースのテスト・アプリケーション ― で実行する手法を紹介します。

RESTful な Web API

RESTful な Web API が使用する HTTP および REST (Representational State Transfer) 原則は、以下のもので構成されています。

  • API のベース URI (Uniform Resource Identifier)
  • API がサポートしているデータ (通常は JSON 形式のデータ)
  • API が GETPUTPOSTDELETE の各メソッドを使用してサポートしている一連の操作

また、RESTful な API のテスト・ツールとしての JMeter の機能と、クラウド・ベースのアプリケーションのテストとの関連性について説明します。マルチテナンシーはクラウドの重要な特徴であることから、データの完全性を確実にするためにプログラムによってデータを分離および取得する手段を組み込む手法も紹介します。さらに、保守性、再利用性、モジュール性を促進する、効果的な JMeter テスト・スクリプト (テスト計画または JMX ファイルとしても知られています) の作成方法や、構成ファイルとプロパティー・ファイルを使用して同じスクリプトを複数の環境で実行可能にする方法も紹介します。

この記事では、読者が JMeter の UI を熟知していること、JMeter の使用経験が十分にあることを前提とします。

スクリプトの再利用を最大限にするためのプロパティーの設定場所

通常、クラウド対応アプリケーションは、迅速かつ容易に複製してデプロイできるため、複数の環境でテストすることが可能です。複数の環境で自動化スクリプトをテストおよび実行する必要がある場合は、JMeter 内で 1 つの独立したプロパティー・ファイルにアプリケーション・サーバーやデータベースなどのリソースに接続するためのデータ (ログイン・クレデンシャルを含む) を定義すると有益です。

JMeter のプロパティーと変数は、JMETER_HOME/bin ディレクトリー内の 3 つのファイルで定義されます。JMeter は起動時に、これらのファイルを次の順でロードします。

  1. jmeter.properties
  2. ユーザーが定義する、オプションのプロパティー・ファイル (ユーザー・プロパティー・ファイル)
  3. system.properties

JMeter の実行中に新しいプロパティーを追加したり、既存のプロパティーを変更したりした場合には、変更を適用するために JMeter をいったん終了して再起動する必要があります。

jmeter.properties ファイルに格納するのは、JMeter アプリケーション自体に関連するプロパティーです。このファイルには、JMeter のプログラムまたはフレームワークに固有のプロパティーのみを保持するようにしてください。例えば、管理者のユーザー名とパスワードなど、テスト環境に固有で、テスト対象のアプリケーションに関連付けられたすべてのスクリプトにグローバルなプロパティーと変数は、(任意の名前を付けた) 別個のファイルを作成して格納します。jmeter.properties ファイル内で、user.properties を設定している箇所のコメントを外し、user.properties の値にこの作成したファイルの名前を設定します。リスト 1 の例では、この値として myuser.properties を設定しています。

リスト 1. jmeter.properties でユーザー・プロパティー・ファイルを指定する
# Should JMeter automatically load additional JMeter properties?
# File name to look for (comment to disable)
user.properties=myuser.properties

リスト 2 のサンプル・ユーザー・プロパティー・ファイルに、ユーザー・プロパティー・ファイルで変数を定義する際のフォーマットを示します (定義の等号の左辺にスペースを含めることはできませんが、プロパティー値には、必要に応じてスペースを含めて構いません)。

リスト 2. サンプル・ユーザー・プロパティー・ファイル
#----------------------------------------------------------------
# FVT API Test Environment parameters
#----------------------------------------------------------------
#
# --- Login Credentials
USER_LOGIN=admin@in.ibm.com
USER_PASSWORD=password
#
# --- Application Server
APP_SERVER=localhost
APP_PORT=80
APP_CONTEXT=ctx
PROTOCOL=http
#
# --- Database Server${DB_NAME}
DB_HOST=localhost
DB_PORT=50000
DB_NAME=dbname
DB_USER=dbadmin
DB_PASSWORD=dbpassword

JMeter の 3 つ目のプロパティー・ファイル (system.properties) は、すべてのスクリプトに対して定義する必要があるシステム全体のプロパティー用に確保してください。例えば、すべてのスクリプトで特定のデータベース・サーバーを使用する場合は、関連するプロパティーを system.propterties ファイル内で指定することができます。

JMeter の「User Defined Variables (ユーザー定義変数)」コントロール・パネル (図 1 を参照) には、ユーザー・プロパティー・ファイル内で定義されているプロパティーが JMeter スクリプトによってどのように読み込まれるかが示されます。

図 1. ユーザー・プロパティー・ファイル内で定義されている構成データを JMeter スクリプトが読み込む方法
ユーザー・プロパティー・ファイル内で定義されている構成データを JMeter スクリプトが読み込む方法を示す、JMeter の「User Defined Variables (ユーザー定義変数)」コントロール・パネルのスクリーン・キャプチャー

このコントロール・パネルの「Value (値)」列の各項目は、以下の形式になっています。

${__property(VARIABLE_NAME,VARIABLE_NAME)}

例えば、ユーザー・プロパティー・ファイル内で定義されている USER_LOGIN 変数は、${__property(USER_LOGIN, USER_LOGIN)} 関数としてスクリプトに読み込まれます。括弧内の最初の USER_LOGIN は、プロパティー・ファイルで定義されている変数の名前です (これは、コントロール・パネルの「Name (名前)」列に記載されます)。2 番目のインスタンスは、その変数がプロパティー・ファイルで定義されていない場合に使用されるデフォルト値またはフォールバック値です。

プロパティー・ファイルで変数を定義する際や、変数を JMeter スクリプト内の変数として定義する際に適用される確固とした規則はありません。ただし、複数の JMeter スクリプト全体にわたって変数定義の一貫性を維持し、不要な重複を減らすには、以下の 2 つのガイドラインが役立ちます。

  • 複数のスクリプトで一貫して同じ値を使用する場合、そのデータをユーザー・プロパティー・ファイルまたは system.properties ファイルのいずれかで定義します。このような値の例には、システム変数 (データベース名やサーバー名など)、実行スコープが指定された変数 (ロギング・レベルなど) があります。
  • スクリプトによって変わる可能性のある値をいくつかのスクリプトで使用する場合、その値をスクリプト変数として定義するか、外部データ・ファイル (コンマ区切り値 (CSV) ファイルなど) で定義します。

JSON テンプレート・ファイルを使用したペイロードの分離

クラウド API の多くは、JSON ペイロードを入力として要求します。JSON は、エレメントの中にネストできる、構造化された一連のエレメントを定義します。これらのエレメントのそれぞれが、名前と値のペアを 1 つ以上定義します。機能テストでは、指定されたフォーマットでデータを繰り返し入力する必要があります。例えば、典型的な REST API 呼び出しでは、JSON ペイロードを REST HTTP リクエストの本体に入れて渡します。一般にはそのペイロードにハード・コーディングしたデータを組み込みます。このようなハード・コーディングされたデータは、複数のテストで繰り返され、スクリプト全体に分散しているのが通常です。

この手法でよくある問題は、― API パラメーターが変更されたことなどが理由で ― JSON 構造 (または JSON データ) が変更されると、JMeter テストを調べて該当する HTTP リクエスト本体を探し、新しい要件と一致するように JSON 構造 (および JSON データ) を変更しなければならないことです。その JSON 構造を使用する複数の JMeter テスト・ケースで合わせて何千もの HTTP リクエストがあるとしたら、編集作業を何度も繰り返さなればなりません。

それよりも有効な手法は、JSON 構造のテンプレートを作成し、データを代入する置換文字列を定義することです。JSON テンプレートにはハード・コーディングされたデータ値を一切含めずに、代わりにスクリプトの実行時に実際のデータがロードされる参照変数を定義します。その上で、テンプレートを JMeter スクリプト内の変数に読み込んで、HTTP リクエスト本体の中で代入します。

リスト 3 に、従来の JSON ペイロードの定義方法を示します。

リスト 3. JMeter テスト計画での静的 JSON 定義
{
   "Customer":{
      "CustomerType":"DIRECT",
      "CustomerNumber":"1234567890",
      "Organization":{
         "OrgName":"IBM",
         "Phone":"999-999-9999",
         "AddressSet":[
            {
               "AddressLine1":"Tech Park One",
               "AddressLine2":"",
               "AddressType":"MAILING",
               "City":"Pune",
               "Country":"India",
               "State":"Maharashtra",
               "StateCode":"MH",
               "PostalCode":"411006"
            }
         ],
         "Contact":{
            "FamilyName":"Gilra",
            "GivenName":"Shalini",
            "EmailAddress":"shagilra@in.ibm.com",
            "NamePrefix":"Miss",
            "LanguagePreference":"EN_US",
            "WorkPhone":"999-9999"
         }
      }
   }
}

リスト 4 に、JSON をテンプレートで動的に定義する方法を示します。

リスト 4. 外部 JSON テンプレート・ファイルでの動的 JSON 定義
{ 
   "Customer":{ 
      "CustomerType":"${__eval(${STR_CUSTOMERTYPE})}", 
      "CustomerNumber":"${__eval(${STR_CUSTOMERNUMBER})}", 
      "Organization":{ 
         "OrgName":"${__eval(${STR_ORGNAME})}", 
         "Phone":"${__eval(${STR_PHONE})}", 
         "AddressSet":[ 
            { 
               "AddressLine1":"${__eval(${STR_ADDRESSLINE1})}", 
               "AddressLine2":"${__eval(${STR_ADDRESSLINE2})}", 
               "AddressType":"${__eval(${STR_ADDRESSTYPE})}", 
               "City":"${__eval(${STR_CITY})}", 
               "Country":"${__eval(${STR_COUNTRY})}", 
               "State":"${__eval(${STR_STATE})}", 
               "StateCode":"${__eval(${STR_STATECODE})}", 
               "PostalCode":"${__eval(${STR_POSTALCODE})}", 
            } 
         ], 
         "Contact":{ 
            "FamilyName":"${__eval(${STR_FAMILYNAME})}", 
            "GivenName":"${__eval(${STR_GIVENNAME})}", 
            "EmailAddress":"${__eval(${STR_EMAILADDRESS})}", 
            "NamePrefix":"${__eval(${STR_NAMEPREFIX})}", 
            "LanguagePreference":"${__eval(${STR_LANGUAGEPREFERENCE})}", 
            "WorkPhone":"${__eval(${STR_WORKPHONE})}", 
         } 
      } 
   } 
}

リスト 3 の JSON エンティティーには、ハード・コーディングされたデータしか含まれていません。それとは対照的に、リスト 4 のテンプレートには参照変数名だけが含まれているため、あらゆる JMeter テスト計画でこのテンプレートを使用することができます。実際のデータは CSV データ・ファイルに別に格納されます。これについては、次のセクションで説明します。

リスト 4 の JSON は、定義された代入変数のそれぞれに対して JMeter の __eval() 関数を呼び出すことに注目してください。この追加により、JMeter スクリプトの実行時に変数を評価できるようになります。

図 2 と図 3 に、JMeter テスト・スクリプトに JSON エンティティー・テンプレート・ファイルを指定する方法を示します。まず図 2 に、「HTTP Request (HTTP リクエスト)」コントロール・パネルを示します。

図 2. テストでテンプレート・ファイルの内容を使用する
テストでテンプレート・ファイルの内容を使用するように構成された、JMeter の「HTTP Request (HTTP リクエスト)」コントロール・パネルのスクリーン・キャプチャー

図 2 の例で CUSTOMER_JSON 変数が表しているのは、JSON の Customer エレメント全体です。この変数が _eval() 関数で囲まれて、HTTP リクエスト本体として (「Parameters (パラメータ)」タブの「Send Parameters With the Request (リクエストで送るパラメータ)」という見出しの下に) 表示されています。したがって、図 2 でのリクエスト本体は ${_eval(${CUSTOMER_JSON})} です。

この CUSTOMER_JSON 変数を定義しているのが、図 3 に示す「User Parameters (ユーザーパラメータ)」コントロール・パネルです。

図 3. JMeter スクリプトで JSON テンプレート・ファイルを読み込む
スクリプトが JSON テンプレート・ファイルを読み込む方法を示す、JMeter テストの「User Parameters (ユーザーパラメータ)」コントロール・パネルのスクリーン・キャプチャー

図 3 では、CUSTOMER_JSON 変数の値は、JSON テンプレート・ファイルのパスをパラメーターとして指定した FileToString() に設定されています。これにより、JSON エンティティー・テンプレート・ファイルの内容全体が CUSTOMER_JSON 変数に読み込まれます。その結果、JSON エンティティー・テンプレート・ファイルの内容が実行時に評価され、すべての定義済み置換文字列がそれらに対応するデータに代入されます (代入変数を実際のデータに関連付ける方法については、次のセクションで説明します)。

JMeter の JSON エンティティー・テンプレート・ファイルは、JMeter テスト・スクリプトの外部にあるため、これらのファイルを別個のディレクトリー (例えば、JMETER_HOME/tests/jsontemplates) に格納することができます。JMeter テスト計画から JSON エンティティー・テンプレートにアクセスする際には、JMETER BIN ディレクトリーを基準とした相対名を指定します。以下はその一例です。

../tests/jsontemplates/customer_template.json

これらのテンプレートを JMETER_HOME ディレクトリーの外部に格納することもできます。その場合には、絶対パスを指定する必要があります。


CSV Data Set Config エレメントを使用したデータの抽象化

JMeter テスト計画からテスト・データを分離するのは、最初は余分な作業のように思えるかもしれませんが、この分離によってテストが簡潔になり、テストの管理も容易になります。こうすることのメリットは、テストに変更を加える必要が生じた場合にすぐに実感するはずです。テスト・データのなかには、それぞれのテスト計画のローカルな場所に残されたままとなるものもあるかもしれませんが、テスト・データの大半は (前に説明した) プロパティー・ファイルまたは CSV データ構成ファイルのいずれかの外部ファイルに抽象化されます。その結果、テスト・スイートを保守しやすくなり、ほとんどの場合は JMeter テスト計画を編集しなくてもデータ値を変更できるようになります。

JMeter は CSV ファイルに、コンマで区切られたデータの行を格納します。CSV ファイルのテスト・データを実行時に動的に読み込むには、JMeter フレームワークの CSV Data Set Config (CSV データ・セット構成) 機能を使用します。テスト・データを CSV として格納すると、複数のデータ・オブジェクト/変数を表すデータや、ループ処理の複数のイテレーションを表すデータを各行に格納することができるというメリットもあります。JMeter 2.3.4 以降では、ファイルの先頭行として CSV ヘッダーを指定することもできるようになっています。この場合、定義されたデータ値は、ヘッダーを構成する区切り文字列の名前で格納されます。通常、ヘッダーに続く各行のデータが、ループの 1 回のイテレーションを表します。この意味では、JMX スクリプトはほとんど「データ駆動型」であり、テスターは JMX スクリプトを変更することなしに、CSV ファイル内のデータを変更することができます。

複数のテスト・スレッドでデータを共有することや、複数の CSV ファイルにテスト・データを格納することもできます。例えば、一連のユーザー・クレデンシャルを使用してログインした後、そのユーザー向けの注文書を作成するテストがある場合、2 つの CSV ファイルを作成し、一方のファイルにユーザー・クレデンシャルを格納して、もう一方のファイルに注文情報を格納することができます。場合によっては、複数の JMX スクリプトが同じ 1 つの CSV ファイルにアクセスしなければならないこともあります。そのような場合には、複数のスクリプトがファイルにアクセスできる場所に CSV ファイルを配置する必要があります。

CSV ファイル内に定義されるイテレーション・データには、一般に変数名が関連付けられます。これらの変数名は、コンマで区切ってヘッダー内で定義します。変数名とデータ値の数は、1 対 1 で対応します。JMeter はファイルの各行を処理するときに、対応するデータ値をその位置に関連付けられている変数名に割り当てます。リスト 5 に、サンプル CSV ファイルの内容を記載します。

リスト 5. サンプル CSV ファイル (customer.csv)
"STR_TESTCASE","STR_CUSTOMERTYPE","STR_CUSTOMERNUMBER","STR_ORGNAME","STR_PHONE",
"STR_ADDRESSLINE1","STR_ADDRESSLINE2","STR_ADDRESSTYPE","STR_CITY","STR_COUNTRY",
"STR_STATE","STR_STATECODE","STR_POSTALCODE","STR_FAMILYNAME","STR_GIVENNAME",
"STR_EMAILADDRESS","STR_NAMEPREFIX","STR_LANGUAGEPREFERENCE","STR_WORKPHONE", 

"Testcase1","DIRECT","1234567890","IBM","999-999-9999","Tech Park One","","MAILING",
"Pune","India","Maharashtra","MH","411006","Gilra","Shalini","shagilra@in.ibm.com","Miss",
"EN_US","999-9999", 

"Testcase2","DIRECT","1234567891","IBM","999-999-9999","Tech Park One","","MAILING",
"Pune","India","Maharashtra","MH","411006","Prakash","Prem","premprakash@in.ibm.com",
"Mr","EN_US","999-9999", 

"Testcase3","DIRECT","1234567892","IBM","999-999-9999","550, Kings Street","","MAILING",
"Littleton","United States","MA","MA","1460-1250","Tuohy","Tom","tuohy@us.ibm.com","Mr",
"EN_US","999-9999",

変換スクリプトをダウンロードできます

JSON ペイロードを JSON テンプレート・ファイルに変換したり、データを CSV ファイルに変換したりするための実装の詳細は、面倒な作業になることがあります。その作業では、属性と値のペアごとに参照変数を定義して、対応するデータ値が格納されている CSV ファイルにマッピングしなければなりません。この時間のかかる作業を楽にするために、この記事では、指定された JSON ペイロードに対してこれらの作業を行うサンプル Windows バッチ・ファイルを用意しています。このバッチ・スクリプトとその使用方法の説明を入手するには、「ダウンロード」を参照してください。

JMeter がリスト 5 の CSV ファイルを処理する際には、最初のイテレーションで PuneSTR_CITY 変数に割り当て、IndiaSTR_COUNTRY 変数に割り当てるといった具合に処理します。次の 2 つの行/イテレーションでも同じ処理を行いますが、使用する値は、その特定の行に指定された値です。スクリプトが実行されると、指定された変数がそれぞれに対応する値をロードして格納します。この処理は、変数が上書きされるまで、またはスクリプトが終了するまで続きます。うっかりして変数を上書きしないように、変数の名前は慎重に指定してください。また、変数の場所はスクリプトそのものの中では定義されないため、JMeter スクリプトをデバッグするときには、変数がどこに定義されているのかを知ることが重要です。そのため、CSV ファイル内の変数名には一貫した命名規則を使用すると役立ちます。

図 4 に、「CSV Data Set Config (CSV データ・セット構成)」コントロール・パネルで CSV ファイルを指定する方法を示します。

図 4. JMeter で CSV ファイルを指定して読み込む
CSV データ・ファイルを指定して読み込むために使用する、JMeter の「CSV Data Set Config (CSV データ・セット構成)」コントロール・パネルのスクリーン・ショット

図 4 に示されている「Filename (ファイル名)」フィールドには、読み込む対象の CSV ファイルの相対パスが設定されています。「Allow quoted data? (引用符付きデータの許可)」の値が「True (許可)」に設定されているのは、CSV ファイル内のデータ値は引用符で囲まれるためです。「Recycle on EOF? (EOF でのリサイクル)」オプションが「False (しない)」に設定され、「Stop thread on EOF? (EOF での停止)」が「true (する)」に設定されているため、スレッドはファイルの終わり (EOF) に達した時点で停止します。


While Controller を使用したループ処理

テスト・データを別個の「CSV Data Set Config (CSV データ・セット構成)」ファイルに隔離した後は、そのデータ・セットを使用して極めて簡単に、一連の似たような個別のアクションを繰り返すことができるようになります。JMeter には、イテレーションに役立つ While Controller のようなループ処理用の構成体があります。複数のテスト・アクションをループ処理用の構成体の下で編成することで、必要なデータ駆動型テストのすべてを 1 つのテスト計画のなかで実行することができます。

この手法は、クラウドをテストする場合に役立ちます。それは、複数のアクセス・ロールや異なるデータ・セット (正の値、負の値、境界値など) から API へのアクセスをテストできるからです。ループ処理によって、1 つの API テスト・ターゲットに対し、テストで置換されるすべてを 1 つのテスト計画に含めることができるため、少なくとも 20 倍速くテスト・ケースを作成することができます。

図 5 に、「While Controller」コントロール・パネルを使用して JMeter に CSV ファイル内データのループ処理を指示する方法を示します。

図 5. CSV ファイル内のすべてのデータをループ処理する
JMeter にCSV ファイル内のすべてのデータをループ処理するように指示する、JMeter の「While Controller」コントロール・パネルのスクリーン・キャプチャー

図 5 では、「Condition (function or variable) (条件 (関数または変数))」フィールドに jexl() 関数が設定されています。この関数は、CSV データ・ファイルにある変数を EOF に対して比較し、CSV ファイル内にそれ以上データ行がない場合には、JMeter にループを終了するよう指示します。条件は、最終的に false に評価される任意の変数または関数にすることができます。


BeanShell によるスクリプト作成

BeanShell スクリプト言語 (「参考文献」を参照) を使用することで、JMeter スクリプトに Java プログラミングを含めることができます。BeanShell によるスクリプト作成が役立つのは、例えばスクリプトで、JMeter の正規表現抽出 (Regular Expression Extractor) によって取り込んだ変数を操作しなければならない場合です。実行時に、BeanShell スクリプトは渡されたプログラムを実行して、その結果を返します。

一部のクラウド・アプリケーションでは、API コマンドから返されたレスポンス・データ (通常は JSON 形式) に何らかの変更を加えてから、そのデータを別の API コマンドへのリクエスト・データとして使用します。このように未知の動的データを扱うのは、スクリプトでプログラミングを使用できない限り、厄介で難しい場合があります。BeanShell によるスクリプト作成では、JSONObject クラス・ライブラリー (「参考文献」を参照) を利用して、実行時に JSON ペイロードを操作したり、JSON ペイロードの属性値を読み込んだりすることができます。JMeter スクリプトで JSONObject を使用するには、java-json.jar (ダウンロード・リンクについては「参考文献」を参照) を JMETER_HOME/lib フォルダーにコピーすることによって、この JAR を JMeter のクラス・パスに含めます。

さまざまな目的で BeanShell スクリプトを定義して使用するには、いくつもの方法があります。BeanShell PreProcessor または BeanShell PostProcessor を使用すれば、JMeter BeanShell Sampler 内のコードを、このサンプラーの実行前または実行後のいずれかに適用することができます。あるいは BeanShell アサーションを使用して、例えば JMeter 変数が期待される値を保持しているかどうかなどの条件をテストすることもできます。

BeanShell スクリプトを定義して使用するための通常の手順は、以下のとおりです。

  1. JMeter で、BeanShell Listener、BeanShell PreProcessor、BeanShell PostProcessor、または BeanShell Sampler を作成します。
  2. BeanShell スクリプト内で vars.get("variable") を使用して、変数を取得します。
  3. Java プログラミング言語を使用して BeanShell スクリプトを処理します。
  4. BeanShell スクリプト内で vars.put("variable") を使用して、処理された変数を指定の JMeter 変数 (既存の変数または新しい変数のどちらでも指定可能) に戻します。

リスト 6 に記載するサンプル BeanShell スクリプトは、リスト 3 の JSON の第 3 レベルにネストされている GivenName 値と WorkPhone 値を変更します。

リスト 6. BeanShell によるスクリプト作成を利用して 2 つの JSON 値を変更する
custPayload= vars.get("testResp");
org.json.JSONObject custJSON= new org.json.JSONObject(custPayload);

if (custJSON.has("Customer") && custJSON.get("Customer")!= null) {
   org.json.JSONObject contactJSON = custJSON.getJSONObject("Customer").getJSONObject(
   "Organization").getJSONObject("Contact");
   contactJSON.put("GivenName", "Shalini");
   contactJSON.put("MobilePhone", "9923406159");
}
vars.put("updatedCustPayload", custJSON.toString());

これで、リクエストの API UPDATE コマンド内で ${updatedCustPayload} 変数を使用することができます。

BeanShell によるスクリプト作成を利用すれば、他にもさまざまな方法で (算術演算を実行したり、変数の値を取得したり、特定の変数の値を他の値で置き換えたりするなど) JMeter 変数または JSON データを操作することができます。概して BeanShell は、JMeter で直接サポートされていないタスクを実行する際に役立ちます。


Module Controller を使用した、再利用可能なフラグメントのモジュール化

テスト計画の複雑な部分に変数と関数が数多く含まれていることは珍しくありませんが、そのようなセグメントが他のテスト計画でも何度か使用される場合はよくあります。その場合、セグメントをいくつかのサブモジュールに分割して、他の場所でも再利用できるようにすれば、保守作業を軽減することができます。こうすれば、再利用可能な機能に変更が必要になった場合、一箇所でその機能を変更するだけで済みます。

JMeter の Module Controller は、実行時にテスト計画のフラグメントを現行のテスト計画に代入するためのメカニズムです。代入するフラグメントは、任意のスレッド・グループに配置することも、WorkBench 上に配置することもできます。Module Controller が使用するフラグメントには、一意の名前を設定する必要があります。テスト計画のリロード時には、その名前を使用してターゲットの Module Controller を見つけるからです。

一例として、図 6 に Module Controller の配置場所、ならびにスクリプト内で呼び出されるモジュールの配置場所の例を示します。

図 6. Module Controller と、このコントローラーが指すモジュールの配置場所
Customer Service モジュールのログイン・ルーチンおよびログアウト・ルーチンの間に Module Controller が作成されていて、このコントローラーが指す Register Customer モジュールが WorkBench 内に作成されている JMeter テスト計画のスクリーン・キャプチャー

図 6 に示されているテスト計画では、Register Customer が別個のモジュールとして定義されていて、「WorkBench (ワークベンチ)」セクションに配置されています。Login User ルーチンと Logout User ルーチンの間に配置されている Module Controller (Module Controller - Register Customer) は、この Register Customer モジュールを指しています。スクリプトの実行時に、この Module Controller はテスト計画の Register Customer モジュールを、Module Controller 自身が配置されている位置に代入します。

図 7 に、スクリプト内で Module Controller を定義する方法を示します。

図 7. WorkBench 内で定義されている単純なコントローラーを指す Module Controller
WorkBench 内で定義されている単純なコントローラーを指す、JMeter の Module Controller のスクリーン・キャプチャー

図 7 では、使用可能なすべてのモジュールを一覧表示する「Module To Run (実行するモジュール)」フィールドのドロップダウン・リストから、「Register Customer (顧客の登録)」モジュールが選択されています。

再利用可能なコンポーネントを同じスクリプト (JMX ファイル) 内で再利用する際には、Module Controller を使用してください。再利用可能なフラグメントを他のスクリプトでも使用するとしたら、そのフラグメントを別個の JMX ファイルに移動し、Include Controller を使用して呼び出します。次のセクションでは、この Include Controller について詳しく説明します。


Include Controller による再利用可能な外部 JMeter ファイルのインクルード

JMeter の Include Controller は、JMX ファイル (親スクリプト) が別の JMeter スクリプト (子スクリプト) を呼び出せるプレースホルダーとなります。スクリプトを小さな複数のスクリプトまたはモジュール/ルーチンに分割し、これらのサブルーチンを使用してテスト・スイートを構築することで、スクリプト作成においてモジュール性が実現され、包含性および再利用性を強化することができます。スクリプトの管理および保守を容易にするには、Include Controller を使用して、再利用可能なコード・スニペットまたは前提条件 (Login User や Register User など) を分離してください。

Include Controller を使用するには、最初に再利用可能なルーチン (Login Admin User など) を格納する子 JMX ファイルを作成します。図 8 に示すサンプル子スクリプトは、Include Controller を介して親スクリプト内に含めることができます。

図 8. 子 JMX ファイル (LoginUser.jmx)
子スクリプト (LoginUser.jmx) のスクリーン・キャプチャー

図 8 の子スクリプトが定義しているテスト計画には、Login User に対する HTTP リクエストを設定したサンプラーが含まれています。HTTP リクエスト内のプロトコル、サーバー名、およびその他の設定に使用する変数は、親スクリプトで定義します。

次のステップでは、親スクリプトの中で、子スクリプトを呼び出す箇所に Include Controller を追加して、Include Controller が子 JMX ファイルのパスを指すようにします。図 9 に、親スクリプトに定義された Include Controller を示します。

図 9. 親 JMX ファイルに Include Controller を追加する
親スクリプトに定義された Include Controller のスクリーン・キャプチャー

図 9 に示されている「Include Controller」コントロール・パネルの「Filename (ファイル名)」フィールドには、相対パスを含む子 JMX ファイル名が入力されています。

子 JMX ファイルは、Include Controller にアクセス可能な親に定義されている変数であれば、どの変数にでもアクセスすることができます。親 JMX ファイルも、子 JMX ファイルに定義されている変数を使用することができます。


正規表現の使用

JSON が REST 操作のリクエスト・ペイロードである場合、そのレスポンスは JSON 形式であるか、文字列表現であるかのいずれかです。操作が完了したら、レスポンスの文字列、エラー・コード、およびエラー・メッセージの文字列を抽出して、その機能が期待通りに動作しているかどうかを検証する作業が必要になります。変数に含まれるレスポンス・データを抽出するには、その手段として JMeter の正規表現機能を使用することができます。

図 10 に、JMeter の「Regular Expression Extractor (正規表現抽出)」コントロール・パネルで単純な正規表現抽出を作成する方法を示します。

リスト 10. 単純な正規表現抽出
JMeter の単純な正規表現抽出のスクリーン・キャプチャー

図 10 では、正規表現の構文を使用して抽出された値は「Reference Name (参照名)」(この例では「user」) に格納されます。「Regular Expression (正規表現)」フィールドには、特定のデータを抽出するためにレスポンスに対して実行する正規表現の構文 (図 11 では、「\"LoginName\":\"(.*?)\"」) を指定します。以下に、よく使用される JSON レスポンス・データの正規表現の構文の例を記載します。

  • \s*(.+)\s* ― レスポンス文字列全体を抽出します。
  • \"LoginName\":\"(.*?)\" ― 「"LoginName": “abc@testmail.com”」を抽出します。
  • \"CustomerId\":(\d+) ― 「"CustomerId": 2000006」を抽出します。

図 10 の「Template (テンプレート)」フィールドで $1$ は、参照変数のグループ化を表します。「Default Value (デフォルト値)」フィールドには、正規表現がマッチしない場合のデバッグを目的としたデフォルト値を入力します。慣例に従って、デフォルト値を指定するのは、スクリプト作成段階で正規表現パターンを追加してテストするときのみにしてください。


機能テスト用 JMeter スクリプトのパフォーマンス・テスト向け拡張

理想的には、アプリケーションのパフォーマンス・テストには、ユーザー数の急増、システム負荷の増加という 2 つのシナリオを取り込みます。既存の機能テストのシナリオが基本的な REST 関数を網羅していれば、そのシナリオを拡張して、クラウド・インフラストラクチャーでホストされる REST サービスのパフォーマンス・テスト用に更新するのは簡単です。アプリケーションの負荷テストは、個々のサーバーに送信するリクエストの数を変更することで実行することができます。リクエスト数を制御するには、ループのイテレーションを適切なだけ使用する立ち上げ (Ramp-Up) 期間を構成するという方法を使用することができます。

一例として、以下のアルゴリズムに基づく単純な REST 原則のセットを実行して検証するテスト計画があるとします。

  1. HTTP POST メソッドを実行して顧客オブジェクトを作成する。
  2. HTTP GET メソッドを実行して顧客オブジェクトの作成を検証する。
  3. HTTP PUT メソッドを実行して顧客オブジェクトの変更を検証する。
  4. HTTP DELETE メソッドを実行してオブジェクトの削除を検証する。

この単純な機能テスト計画 ― 元々は RESTful な API の機能テスト・シナリオ用に作られた計画 ― に少しだけ手を加えて、クラウド環境にデプロイされているサーバーを対象としたパフォーマンス・テスト・スクリプトにすることができます。

  1. テスト計画の「Thread Group (スレッドグループ)」コントロール・パネルにナビゲートします (図 11 を参照)。
    図 11. パフォーマンス・シミュレーション設定の例
    パフォーマンス・シミュレーション設定を表示する JMeter 「Thread Group (スレッドグループ)」コントロール・パネルのスクリーン・キャプチャー
  2. 「Number of Threads (users) (スレッド数 (ユーザー数))」フィールドに、「${Thread}」と入力します。Thread 変数の値 (ステップ 5 で構成) により、サーバーにアクセスしている仮想ユーザーの数を反映した、使用可能なスレッド数が設定されます。
  3. 「Ramp-Up Period (in seconds) (Ramp-Up 期間 (秒))」フィールドに、「${RampUp}」と入力します。RampUp 変数の値 (ステップ 5 で構成) により、(ステップ 1 で定義したスレッド数に基づく) リクエストの配信速度が決まります。例えば、スレッド数が 10 で、立ち上げ期間が 100 秒の場合、合計 100 秒間でテストの準備ができるようにするために、各スレッドは前のスレッドが開始されてから 10 秒後に開始されます。
  4. 「Loop Count (ループ回数)」フィールドに、「${Loop}」と入力します。Loop 変数の値 (ステップ 5 で構成) により、テスト計画の実行回数が決まります。
  5. 「User Defined Variables (ユーザー定義変数)」コントロール・パネルにナビゲートし、ThreadRampUp、および Loop をグローバル変数として定義します (図 12 を参照)。シミュレートする負荷ごとに、これらの変数に適切な値を割り当てます。
    図 12. パフォーマンス・テストのシミュレーション変数
    パフォーマンス・テストのサンプル・シミュレーション変数を表示する 「User Defined Variables (ユーザー定義変数)」コントロール・パネルのスクリーン・キャプチャー
  6. 図 12 では、Loop の値は 5 に設定されていて、RampUp の値は 50Loop の値は 2 に設定されています。

図 13 に、図 12 で構成されている変数の値に基づき、クラウド・アプリケーションにデプロイされているノード・サーバーのうちの 1 つに対して JMeter を実行した結果を示します。

図 13. パフォーマンス・テストの結果
図 12 で定義されている構成変数の値に基づき、クラウド・アプリケーションにデプロイされているノード・サーバーのうちの 1 つに対して JMeter を実行した結果を示すスクリーン・ショット

図 13 には、パフォーマンス・テストの状態をシミュレートするために、同時リクエストによる重い負荷がサーバーにかけられていることが示されています。


機能テスト用 JMeter スクリプトの信頼性テスト向け拡張

信頼性テストは、特定の条件セットの下で一連のスクリプトを継続的に実行することによって、システム全体の安定性を確実にする方法です。信頼性テストの結果は、ストレス・テスト、機能テスト、およびネットワーク機能のテストの結果と併せて検討してください。

パフォーマンス・テストの場合と同じく、単純な REST 原則を実行して検証するテスト計画を、クラウド・インスタンス上で実行される製品や機能の安定性を判定するのに適した一連の信頼性テスト・スクリプトに変換することができます。

信頼性テストの重要な側面は、何日間も継続的にスクリプトを実行した場合に障害が発生するかどうかを判別することです。テストが失敗するか、スクリプトが強制的に停止されるまでスレッドを実行できるようにするには、「Thread Group (スレッドグループ)」コントロール・パネルの「Forever (無限ループ)」チェック・ボックスにチェック・マークを付ける必要があります。

図 14. JMeter スクリプトの信頼性テスト用設定
信頼性テストを目的に「Forever (無限ループ)」チェック・ボックスにチェック・マークが付けられた JMeter の「Thread Group (スレッドグループ)」コントロール・パネルのスクリーン・キャプチャー

信頼性テストの設定を構成した後は、テストを数日間実行して、JMeter の結果グラフまたは JMeter に用意されているアサーション・オプションを使用して、テスト結果をモニターし続けてください。


まとめ

この記事では、クラウド・ベースのアプリケーションを効果的にテストするために JMeter を利用する方法を紹介しました。この記事は、決して包括的な説明をするものではないので、JMeter の自動化タスクの実装を改善するその他の手法を調査することをお勧めします。JMeter の調査を進めるには、JMeter Wiki (「参考文献」を参照) が絶好の情報源となります。


ダウンロード

内容ファイル名サイズ
Batch file for converting JSON payloadConversion_Script.zip2KB

参考文献

学ぶために

  • Apache JMeter: JMeter のドキュメント、ダウンロード、サンプルについては、JMeter の Web サイトにアクセスしてください。
  • JMeter Wiki: JMeter のウィキを調べてください。
  • JSON Formatter & Validator: このオンライン・ツールを使用して、JSON ペイロードの検証を行ってください。
  • JSONObject: JSONObjectクラスのドキュメントを読んでください。
  • BeanShell: BeanShell のサイトにアクセスして、BeanShell によるスクリプト作成についての詳細を調べてください。
  • Regular expressions: この便利なサイトで RegEx リソースを調べてください。
  • developerWorks の Cloud computing ゾーンを調べてください。ここでは、コミュニティーによる貴重なディスカッションを見つけることや、クラウドに関連する新しい技術リソースについて学習することができます。

製品や技術を入手するために

  • java-json.jar: java-json.jar をダウンロードしてください。

議論するために

  • developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、Wiki を調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing, Java technology
ArticleID=947248
ArticleTitle=Apache JMeter でクラウド・ベースのアプリケーションをテストする
publish-date=10102013