JMeterでログインが必要なシステムのシナリオの作り方
ログイン、ログアウトが必要なWebシステムのシナリオを作成する場合は、一工夫が必要です。
準備
まずはログイン画面からログインして、少し中を操作してからログアウトするというシナリオを作ってみましょう。シナリオの作り方がわからない方は、こちらを参考にしてみてください。
私はこんな感じで作ってみました。もちろんテスト対象のシステムによってログイン機能の作りが違うと思いますので、これは一例として参考にするぐらいにしてください。
シナリオ記録はうまくいったと思います。このシナリオをJMeterで実行すると、HTTPリクエスト的に問題なければこのようにステータスコード:200でテスト正常実行!となります。
しかし、待ってください。HTTPリクエストは正常ですが、戻ってきたレスポンスの中身を確認してみてください。恐らくログイン後の画面のレスポンスを見ると、ログインできていないと思います。
これはJMeterがログイン情報を維持できていないため、ログイン後のリクエストを投げてもログインしていない状態でそのURIにアクセスしたことになり、結果ログイン画面が表示されてしまいました。
前フリはこのぐらいにしておき、本題のログイン認証が必要なシステムのシナリオ作成方法についてやっていきたいと思います。
シナリオにHTTPクッキーマネージャーを追加
シナリオにHTTPクッキーマネージャを追加します。
このようにシナリオに追加されます。特に設定は不要でこのまま使えます。
ログイン情報の変数を追加
リクエスト時のパラメータの値を変数に置き換える
ログインボタンを押す処理のHTTPリクエストサンプラーにユーザ名とパスワードを送信した記録が残っていると思います。その値を変数に置き換えます。
名前の部分が送信フォームのキー項目名、値が実際に送信した値です。値の部分を変数に変更します。変数は、${変数}という形で書きます。変数にしておくことで後で動的に値を変更することができます。
名前はパラメータ名です。ログイン画面側のコードでは、このように定義しています。inputのnameと一致させれば、そこに値がセットされてサブミットされます。
<tr>
<th>ログインID</th>
<td><input name="login_id" type="text"></td>
</tr>
<tr>
<th>パスワード</th>
<td><input name="password" type="password" value="">
</td>
ユーザ定義変数を追加
次にパラメータの値と差し替えた変数を定義するため、シナリオにユーザ定義変数を追加します。
シナリオにユーザ定義変数が追加したら、右側で変数名と値がセットできます。今回はユーザ名とパスワードですので、さきほど設定した変数名を名前欄にセットし、実際にセットする内容を値の欄にセットします。
これで完了です。テストシナリオを実行するとここでセットしたユーザ名とパスワードでリクエストが送信されると思います。
(ログインできない場合)トークンの受け渡しを追加
ユーザ名とパスワードが問題なくセットできているのに、うまくログインできないという場合は何かが足りていない場合があります。
よくあるパターンとしては、ユーザ名とパスワード以外に前画面からのトークンも一緒に送信する必要な場合が挙げられます。
トークンを変数化
その場合は、ログイン処理のサンプラーにトークンのようなものが既にあり、既にプロキシで採取した時のトークンの文字列がセットされていると思います。トークンはアクセスする度に毎回変わるので固定値では使えませんので、こちらも変数に変更します。
トークンは毎回変わるから変数としてセットできないのでは? と思った方がいるといると思いますが鋭いです。そのとおりです。ではどうするのでしょうか?
答えは、ログイン画面表示時に埋め込まれたトークンの値を、ログインボタンを押した時のリクエストにセットするようにすれば解決です。
トークンを抽出
やり方は、ログイン画面のサンプラーの後処理で正規表現抽出を追加して、トークンを抜き出してログイン処理に引き渡します。
ここでレスポンスのBody部から正規表現でトークンの文字列部分のみをヒットさせ、値の部分だけを変数にセットします。この変数をログイン処理のリクエストの変数にセットすればトークンを持ち越せます。
まとめ
- ログイン処理が必要なシナリオを作る場合は、HTTPクッキーマネージャを追加する
- ユーザ名やパスワードは、ユーザ定義変数を使って置き換える
- 前画面からの値の引き継ぎは、正規表現を使って抽出して変数に代入して次につなげる
ログイン処理がないWebシステムはもはや皆無なので、このテクニックは必須になると思います。ログイン機能の作り方によってはこの方法では実現できないかもしれませんが、考え方は似たようなものだと思いますので、これらの処理をどのタイミングで行うかを調整すればよいと思います。
コメント