このトピックはまだ評価されていません - このトピックを評価する

Web テストのオーサリングおよびデバッグの技法

Visual Studio 2005

Josh Christie
ソフトウェア デザイン エンジニア
Microsoft Visual Studio 2005 - Web テストおよび負荷テスト

December 2005
日本語版最終更新日 2006 年 9 月 25 日

適用対象:
   Visual Studio 2005 Team Suite
   Visual Studio 2005 Team Edition for Software Testers

概要: Visual Studio 2005 の Web テストに関して包括的に説明を行います。Visual Studio 2005 における Web テスト エンジンとレコーダがどのように機能するかを始めとし、効率のよい Web テストの作成方法を習得してください。

目次

対象読者
はじめに
Web テストの記録
Web テストの実行および検証
Web テストの共通問題のデバッグ
一歩進んだコード化 Web テスト
まとめ

対象読者

この記事は、Microsoft Visual Studio 2005 Team Edition for Software Tester の Web テスト機能にさらに熟達したいと考えているテスト担当者および開発者を対象読者としています。

はじめに

Microsoft Visual Studio 2005 Team Edition for Software Tester は、Web テストおよびロード テストのための、まったく新しい一連の強力なツールとして登場しました。Web アプリケーションのロード テストは、複数のコンピュータを対象として、数百あるいは数千人のユーザーをシミュレートすることがありますが、その真髄は Web テストの集合にあります。 この記事では、効率のよい Web テストを作成する技法と、所定どおりの稼働を確保するためにそのテストをデバッグする技法を習得したいと考えている、テスト担当者および開発者が対象となっています。

Web テストの記録

Web テスト レコーダの概要

Web テスト レコーダ は、Internet Explorer のオブジェクト モデルにフックし、各種のナビゲーション イベントをリッスンします。 この種の記録の主な利点は、構成上の特別な処置をしなくても、SSL (Secure Sockets Layer) サイトや認証済みの Web サイトを記録できることにあります。

この記録方式の別の一面として、イメージ、カスケード スタイル シート (CSS) ファイル、および JavaScript ファイルなどの従属要求は、Web テストには記録されません。 そのような従属要求は、記録される代わりに、Web テストの実行中の構文解析で HTML ページから取り出されて、自動的に要求として出されます。 この機能のおかげで、Web サイトの表面的な変更に対して Web テストがより柔軟に対応できるようになり、テストにおいて、Web アプリケーションの実際の使用に継続的に焦点を絞ることができます。 必要があれば、この機能を無効にすることができます。それには、要求の ParseDependentRequests プロパティを false に設定します。

この記録方式の欠点は、要求によっては記録されないことがあることです。それには、JavaScript (たとえば、AJAX サイトでの)、ActiveX コントロール、およびある種のポップアップ ウィンドウから出された要求などが含まれます。その理由は、Internet Explorer では常に必要なイベントの発生が行われるとは限らないからです。 たいていの場合は、この記事の後半で説明するとおりに、脱落した要求を元通りに Web テストに手動で追加すれば、そのような問題を解決することができます。

コメントの挿入

記録中にコメントを挿入すれば、効率のよい Web テストを作成するのに役立つことがあります。多数の要求が Web テストに詰め込まれている場合は特にそうです。Web テストでのさまざまな地点で、「ログイン」、「ショッピング カートへの項目 X の追加」といった、どのような論理アクションがとられるかに関するメモを記入するのに、コメントを使用する必要があります。 そのようなコメントは、後で Web テスト エディタで Web テストを修正する際に非常に役に立ちます。

また、コメントを使用して、Web テストを成功させるために追加する必要のある、検証ルールに関するメモをつけることもできます。Web テスト エディタで HTTP 要求のリストを調べるよりも、記録しながらページを参照して、各要求に関して何の検証を行う必要があるかを判断するほうが、はるかに簡単です。

思索時間を念頭に置いた記録

Web テスト要求での ThinkTime プロパティとは、ユーザーが次の要求を出す前に、現在のページで「思索」に費やす時間を指します。 ロード テスト中に、ユーザーの実際の行動を概算するときに、思索時間の遅延が使用されます。Web テストで生成可能なロード量は、思索時間によって大きな影響を受けることがあるので、このプロパティをロード テストではグローバルに使用不可にして、ターゲット サーバーへのロード量の増大を図ることができます。 思索時間を使用不可にすることによって、要求と要求の間で遅延を生じないで、可能な限り速やかにサーバーに対する要求を出すことができます。

Web アプリケーションに対する要求が記録されると同時に、思索時間が Web テスト レコーダで自動的に記録されます。 記録中は、ユーザーが各ページに通常費やす時間の概算を試みてください。 記録が完了したら、各要求ごとに、記録された思索時間を調べることが非常に大切です。 思索時間が不用意に長くなると、Web テストが要求を生成する速度が劇的な影響を受けることがあります。Web テスト ビューアでは、既定では、思索時間はオフになっています。 そういう理由で、思索時間が長くても、すぐには察知されない可能性があります。Web テスト ビューアで思索時間をオンにすると、HTTP 状態列に "Thinking…[n]" が表示され、それは次の要求の開始時点まで続きます。 ロード テストでは、既定では、思索時間はオンになっています。 記録の一時停止中と、コメントの入力中は、思索時間のカウンタも一時停止になります。

Web テストの実行および検証

Web テスト エンジンの概要

Web テスト エンジンを理解する鍵となる考え方は、Web テストは HTTP 層で稼働するということです。Web テストには、HTTP 要求のリストが収められていますが、そのような要求の 1 つ 1 つは、主としてクエリ文字列パラメータ、フォーム パラメータ、および Web サーバーをターゲットとする URL で構成されます。Web テスト エンジンは、その HTTP 要求を実行し、1 つ以上のサーバーから応答を取り出し、そしてタイミング データを収集します。

Web テスト エンジンは、HTTP 層内で稼働するので、JavaScript や ActiveX コントロールなどの、クライアント側スクリプト記述を直接シミュレートすることはありません。Web テストでは、サーバーでのロードの生成に対して注意が払われます。 結果として、Web ページの外観にしか影響を与えないクライアント側スクリプトは、Web テストでは重要視されません。 クライアント側スクリプトでも、パラメータ値を設定したり、結果としてさらに別の HTTP 要求 (たとえば AJAX) の追加につながるものは、サーバーでのロードに影響を与えるので、そのようなスクリプトをシミュレートするように Web テストを修正する必要があるかもしれません。 その種の修正については、この記事の後半で解説します。

記録は Internet Explorer 内で行われるので、何らかの方法で Internet Explorer を使用して Web テストを実施する必要があると、よく誤解されます。 その考えは当たっていません。 すべての要求は、Web テスト エンジンを使用して直接実行されます。Internet Explorer やその他のブラウザとの対話は発生しません。Web テスト エンジンは、HTTP の標準の要求/応答メッセージを使用して、ターゲットの Web サーバーと直接通信します。

同様に、Web テスト ビューアの [Web Browser] タブ上の組み込み Internet Explorer コントロールには、Web テスト エンジンから受信した応答ページしか表示されません。Web テスト エンジンは、ディスク上の一時ロケーションにその応答を書き込んでから、Web テスト ビューアの Internet Explorer コントロール内に一時ファイルをロードします。 他のブラウザ用に設計されているページが、[Web Browser] タブに正しく表示されない場合、応答タブを使用して、そのページを検証することができます。

別の紛らわしい点として、Web ロード テストの実行時に、種々のブラウザ テンプレートが選択される可能性があります。 それらのブラウザ テンプレートは、各要求と一緒に送信される既定の一連の HTTP ヘッダーにのみ影響を与えます。Web サーバーがブラウザ タイプを判別するときに使用するキー ヘッダーは、UserAgent ヘッダーです。 どのブラウザ テンプレートが選択されても、Web テスト エンジンは、標準の HTTP プロトコルを直接使用して要求を出します。

Web テストの検証での Web テスト ビューアの使用

Web テストをロード テストに追加して長時間実行する前に、テストが所定どおりに機能することを確認することが重要です。 そこで、Web テスト ビューアが登場します。Web テスト ビューアを使用すれば、実行中の Web テストを監視するとともに、前のテスト実行のすべての局面を見ることができます。

ms364082.webtesttechniques01(ja-jp,VS.80).gif

図 1

新たに作成した Web テストの検証は、テスト実行の結果に目を通して、テストに合格したかどうかを確かめるだけにとどまりません。 たとえば、検証ルールを定めていない Web テストの場合、合格とは、何も例外はスローされず、どのルールに対する違反もなく、何の HTTP エラーも起きなかったことを意味するにすぎません。 実行中にエラーをまったく生じなかったこと以外に、ターゲットの Web アプリケーションで Web テストが正しい行動をとったことを確認することで、検証は成立します。 各要求ごとに応答を見直して、正しいことを確認することが大切です。

以下の表は、Web テストの検証時のチェック項目と、各種の問題に関する追加情報を一覧で示しています。

表 1

チェックする問題点追加情報/必要な修正点
HTTP 要求エラーHTTP エラーは、400 ~ 599 の範囲の応答状況コードによって示されます。 一般的に、何が問題の原因かを示す応答本体が HTTP エラーに示されます。

たとえば、401 Unauthorized エラーは、Web テストのルート ノード上でユーザー名とパスワードを構成する必要があることを示し、 404 Not Found エラーは、記録がとられた後で Web アプリケーションが変更されたことを示し、 500 Internal Server エラーは、一般的に、Web アプリケーション内のバグを示すと考えられます。
従属要求が見つからない最上位の要求に従属する要求が見つからないために、その最上位の要求は失敗したように見えます。 これは、Web アプリケーションの HTML に問題があることを示す可能性があります。 要求に対する ParseDependentRequests プロパティを無効にすれば、このエラーを抑止することができます。 そうすれば、イメージ、CSS、および JavaScript などの従属要求が、構文解析によって自動的に HTML から取り出されて別途要求されることはなくなります。
抽出および検証のルールの障害抽出および検証のルールの障害は、[Details] タブ上に示されます。 通常、このような障害が起きるのは、ログイン ページあるいはエラー ページへのリダイレクトなどの、想定外の内容が収まったページが Web サーバーから戻されたためです。

抽出ルールの障害の場合は、「X was not found in the Web test context (Web テスト コンテキスト内に X が見つからない)」といったエラーが、その後の要求で起きる場合が多くあります。
テスト レベルの例外テスト レベルの例外は、最後に正常に完了した要求の後で、ノードとして Web テスト ビューアに示されます。 テスト レベル例外には、WebTestPlugins、PreWebTest、および PostWebTest イベント ハンドラ内の例外や、コード化された Web テスト内の不特定の要求での例外などがあります。
要求レベル例外要求レベル例外は、個々の要求が失敗する原因になりますが、Web テストは引き続き稼働できます。 このような例外には、WebTestRequestPlugins、PreRequest、および PostRequest イベント ハンドラからスローされる例外や、抽出および検証のルールからスローされる例外などがあります。 例外メッセージや、スタック トレース (ある場合) が、Web テスト ビューアの [Details] タブの下部に示されます。
サーバーから誤ったコンテンツが戻される多くの場合、Web テスト ビューアの [Web Browser] タブおよび [Response] タブ内の各ページを画面上で検査して、Web サーバーから正しいコンテンツが戻されていることを検証します。

Web テストの正常稼働を検証した後、検証ルールを使用して、このプロセスを自動化することができます。

Web テストの共通問題のデバッグ

実行と記録とで Web サーバーからの応答が異なる

完璧な世界であれば、一連の要求を Web アプリケーションに記録して、Web テストを実行すれば、記録中に見たのと同じ応答がサーバーから返ってくるはずです。 残念ながら、Web アプリケーションは、Web テストの記録中とは異なる動作を、Web テストの実行中にとることがあります。

この種の問題は、さまざまな理由で起きる可能性があり、多くの場合、次のようなエラーが生じることになります。

     Request failed: $HIDDEN1.__VIEWSTATE not found in test context.

このエラーが起きるのは、前に受信した応答ページで見つけることも抽出することもできなかった隠しフィールドを Web テスト コンテキストで使用しようとした場合です。

以下のスクリーンショットは、サーバー エラーが原因のこのような問題を示しています。 最後から 2 番目の要求では、サーバー エラーが原因で、その次の要求が従属する隠しフィールドが、ページ上に存在しないことになります。

ms364082.webtesttechniques03(ja-jp,VS.80).gif

図 2

実行時のサーバーの応答が、記録時のものとは異なる理由は多数あります。 最も一般的ないくつかの理由を、この後の項に要約してあります。 どのような場合でも、検証ルールを要求に追加すれば、サーバーが正しいコンテンツを使用して応答したことを自動的に検証することができます。

1 回のみ使用のデータ

この問題の一般的な原因の 1 つは、1 回のみ使用のデータにあります。たとえば、Web アプリケーションが固有ユーザー名を作成する場合などがこれに当たります。 データ バインディングあるいはランダム値を追加しないでこの種の Web テストを再現すると、重複したユーザー名の作成がテストで試みられたときに、Web アプリケーションでエラーが表示されることがあります。

JavaScript のリダイレクト

JavaScript リダイレクトを使用する (window.location を設定する) Web アプリケーションは、記録時と実行時とでは応答がそれぞれ異なる可能性があります。なぜなら、Web テスト エンジンはスクリプト コードを実行しないからです。 この種の問題は簡単に解決できます。すなわち、スクリプトがリダイレクトする先の URL を挿入し、リダイレクトを実行するページから、必要な抽出ルールを新規の要求に移動します。 この問題は、記録直後の Web テスト内で起きるため、使用する可能性の高い唯一の抽出ルールは ExtractHiddenFields です。

エラー ページへのリダイレクト

サーバー エラーが起きると、Web アプリケーションはエラー ページへのリダイレクトを行うことはありますが、HTTP 400 あるいは 500 レベルの応答コードを戻すことはありません。 これは、Web アプリケーション自体に問題があるか、あるいは Web テストから出された要求に問題があることを示します。 この問題については、ブログ (英語) に詳しく取り上げられています。

ViewState およびその他の動的パラメータの処理

ASP.NET 1.0 に __VIEWSTATE 隠しフォーム フィールドが導入される前でも、Web アプリケーションでは、ページからページへの情報の引き渡しのときに、動的に生成されたフォームおよびクエリ文字列パラメータが使用されていました。 そのような動的パラメータは、Web テストの実行のたびに変わる可能性があるので、Web テストでは特別な配慮が必要になります。 ハードコーディングされたパラメータ値を使用する Web テストは、記録後あまり長く効果を持続しないか、あるいはまったく効果のない場合もあります。

Web テストでは、抽出ルールおよびコンテキスト バインディングの使用によって、動的パラメータを使用したテストを行うことができます。 抽出ルールは、動的値を収容するページに対する要求上に置かれます。 抽出ルールを実行すると、myparam などの構成名を使用して、動的値が Web テスト コンテキスト内に抽出されます。 すると、その後の要求には、{{myparam}} の値を持ったクエリ文字列あるいはフォーム パラメータが入ります。Web テストを実行すると、Web テスト コンテキスト内の値は、{{myparam}} に置き換えられます。

抽出ルールのイベント シーケンスは次のようになります。

  1. Web テスト エンジンが Request1 の実行を開始します。
  2. Request1 がターゲット サーバーに送信されます。
  3. ターゲット サーバーから応答が返されます。
  4. Request1 上の抽出ルールが、応答ページに対して実行されます。
  5. 抽出ルールによって、Web テスト コンテキスト内に項目が配置されます。
  6. Web テスト エンジンが Request2 の実行を開始します。
  7. Request2 上のクエリ文字列パラメータ、フォーム パラメータ、およびコンテキスト関連の他のすべての値が、Web テスト コンテキストのものに置き換えられます。
  8. Request2 がターゲット サーバーに送信されます。
隠しフィールドの自動追跡

Web テストは、__VIEWSTATE などの、動的な隠しフィールドの処理に対するサポートを備えています。Web テストの記録時には、フォーム パラメータおよびクエリ文字列パラメータに対する隠しフィールドの突き合わせが自動的に行われます。 一致するものが見つかると、その隠しフィールドのソースを生成した要求に対して、ExtractHiddenFields ルールが適用されます。 このとき、隠しフィールドが使用されて、要求上のパラメータに対してコンテキスト バインディングが適用されます。

ExtractHiddenFields は特殊な抽出ルールです。その理由は、1 つの値をコンテキストに抽出するルールとは違って、ページ上のあらゆる隠しフィールド値を Web テスト コンテキストに抽出するからです。 通常の抽出ルールは ContextParameter プロパティを使用して、コンテキスト パラメータで使用する名前を判別しますが、ExtractHiddenFields は、コンテキスト内に同時にある隠しフィールドの複数のグループとの区別を付けるためにのみ、そのプロパティを使用します。 たとえば、ContextParameter1 に設定した ExtractHiddenFields ルールは、__VIEWSTATEを "$Hidden1.__VIEWSTATE" として抽出します。

JavaScript によって変更された __EVENTTARGET およびその他の隠しフォーム フィールドの修正

隠しフィールドが OnClick イベント ハンドラにおいて JavaScript によって変更された場合、隠しフィールドの自動バインディングが誤って適用される可能性があります。 これは、Visual Studio 2005 のリリース バージョンにおける既知のバグです。

<input name="btnNext" type="button" value="Next"
onclick="__doPostBack('btnNext', '');" />

ASP.NET サイトでは、この問題が最も起きやすいのは、Web コントロールが __doPostBack() JavaScript メソッドを呼び出して、上記のように __EVENTTARGET 隠しフィールドを設定しようとした場合です。 隠しフィールドの自動バインディングによって、フォーム パラメータは、実際の値 btnNext ではなく、{{$HIDDEN1.__EVENTTARGET}} などの値を持つことになります。 この問題を解決するには、パラメータ値を、JavaScript に設定しようとしている値 (たとえば、btnNext) に設定する必要があります。

記録時の要求の脱落

『Web テスト レコーダの概要』の項で取り上げたとおり、要求によっては、Web テスト レコーダで記録されないこともあります (たとえば、AJAX 要求や一部のポップアップ ウィンドウなど)。 さいわい、Eric Lawrence 氏によって作成された Fiddler leave-ms (英語) という名前の貴重なツールがあり、この問題で役立つかもしれません。Fiddler は、プロキシ サーバーとして稼働し、すべての HTTP トラフィックを代行受信することができます (SSL は未サポートです)。 標準の Web テスト レコーダを使用して記録できない Web テストを訂正するときに、Fiddler を使用するための 2 つのオプションを以下に説明してあります。

ms364082.webtesttechniques04(ja-jp,VS.80).gif

図 3

Fiddler からの Web テストの保存

Web テスト レコーダでいずれかの AJAX、ActiveX、あるいはポップアップ ウィンドウ要求が脱落したときのオプションの 1 つとして、Fiddler を使用してテスト全体を記録します。 Fiddler は、キャプチャした一連の要求を、Visual Studio 2005 テスト プロジェクトに追加できる .webtest ファイルとして保管することができます。

このオプションを最も効果的に使用できるのは、Web テスト レコーダを使用して多数の要求を記録できない場合です。 このオプションの場合の主な制限事項として、Fiddler で作成された Web テストは、隠しフィールドの自動追跡 (__VIEWSTATE の場合など) を使用しません。さらに、この Web テストは、イメージ、CSS、および JavaScript などの従属要求をフィルタ除去しません。

Fiddler からの要求の手動追加

脱落した要求に対する別のオプションとして、Fiddler を使用して、どの要求を手動で Web テストに追加する必要があるかを判別します。 この方式が最善策であるのは、少数の要求が Web テスト レコーダで脱落した場合です。その理由は、隠しフィールドの自動追跡や従属要求のフィルタなどの機能の利点をこれまでどおり活用できるからです。

その場合、Fiddler と Web テスト レコーダを同時に使用して、Web テストを記録するのが最善策です。 そうすれば、2 つの記録内容を比較して、脱落した要求を見つけ出すことができます。 たとえば、AJAX 要求が発生したことを検知した場合のように、要求が脱落したことが明らかな場合、記録中にコメントを挿入すれば役に立ちます。 そのようなコメントには、手動で作成された要求に対するプレースホルダとしての働きがあります。

以下のスクリーンショットは、Fiddler のキャプチャ内容から要求を手動で作成する方法を示しています。 必要なすべての抽出ルール、パラメータ値のコンテキスト バインディング、および ThinkTime を、手動で作成した要求に追加するのを忘れないでください。

ms364082.webtesttechniques05(ja-jp,VS.80).gif

図 4

ms364082.webtesttechniques06(ja-jp,VS.80).gif

図 5

一歩進んだコード化 Web テスト

通常の Web テストは、多種多様な Web テスト シナリオを処理するように設計されます。 データ バインディング、抽出ルール、プラグイン、およびコンテキスト パラメータによって、Web テストの大部分を制御下に置くことはできますが、場合によっては制御を強化する必要が生じます。 コード化 Web テストを使用すれば、Visual C# あるいは Visual Basic から使用できる .NET API を活用することで、ほとんどの制御と拡張性を手に入れることができます。 この API では、次の項に説明されている機能も含め、Web テスト エンジンの機能全体を使用することができます。

いつコードを生成するかとその理由

コード化 Web テストを生成してもよいのは、Web テストの通常の限度に達した後でのみです。 通常の Web テストで最も顕著な限度は、ループ (要求のサブセットを複数回実行できない) およびブランチ (一連の要求を条件付きで実行できない) です。 このコードを生成するその他の理由に、きめの細かいイベント処理と、パラメータ値のプログラマチックな設定があります。

コードを直接編集するよりも、グラフィカルな Web テストを使用したほうが、Web テストの編集がより簡単になりエラーを生じる可能性も低くなります。 したがって、Web テストで可能な限り先に進んでから、はじめてコードを生成する必要があります。 その一環として、抽出ルールおよび検証ルールの追加、データ バインディングのセットアップ、要求グループにまつわるトランザクションの作成、および思索時間の調整などを行います。 Web テストのこのようなすべての局面を対象として生成するコードは、コード化 Web テストをさらにカスタマイズするための堅固な土台としての役割を担います。

この後の項では、コード化 Web テストによって必要とされる機能、あるいは大幅に単純化される機能のいくつかと、例を紹介します。

ブランチ

条件に応じてそれぞれ異なる一連の要求が Web テストから発行される必要のある場合に、コード化 Web テストを使用します。

これを以下の例を使用して解説します。そこでは、Web テストは、データ バインドのユーザー資格情報を使用して Web サイトにログインしますが、システム内にユーザーが存在しない場合は、新規のユーザー アカウントを作成する必要があります。

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.WebTesting;
using Microsoft.VisualStudio.TestTools.WebTesting.Rules;

[DataSource("DataSource1", "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=\"test.mdb\"", DataBindingAccessMethod.Sequential, "Credentials")]
[DataBinding("DataSource1", "Credentials", "UserName",
"DataSource1.Credentials.UserName")]
[DataBinding("DataSource1", "Credentials", "Password",
"DataSource1.Credentials.Password")]
public class BranchingCoded : WebTest
{
  public BranchingCoded()
  {
  }

  public override IEnumerator<WebTestRequest> GetRequestEnumerator()
  {
    // Web アプリケーションのホーム ページへジャンプします。

    WebTestRequest request1 = new WebTestRequest("http://testserver/website");
    request1.ThinkTime = 4;
    yield return request1;

    // ログイン ページへジャンプします。

    WebTestRequest request2 = new WebTestRequest("http://testserver/website/Login.aspx");
    request2.ThinkTime = 16;
    ExtractHiddenFields rule1 = new ExtractHiddenFields();
    rule1.ContextParameterName = "1";
    request2.ExtractValues += new EventHandler<ExtractionEventArgs>(rule1.Extract);
    yield return request2;

    // ログインを試みます。

    WebTestRequest request3 = new WebTestRequest("http://testserver/website/Login.aspx");
    request3.ThinkTime = 6;
    request3.Method = "POST";
    FormPostHttpBody request3Body = new FormPostHttpBody();
    request3Body.FormPostParameters.Add("__VIEWSTATE", this.Context["$HIDDEN1.__VIEWSTATE"].ToString());
    request3Body.FormPostParameters.Add("username",
this.Context["DataSource1.Credentials.UserName"].ToString());
    request3Body.FormPostParameters.Add("password",
this.Context["DataSource1.Credentials.Password"].ToString());
    request3.Body = request3Body;
    yield return request3;

    // ログインに失敗した場合は、新規ユーザー アカウントを作成します。

    if (LastResponse.StatusCode != System.Net.HttpStatusCode.OK)
    {
      WebTestRequest request4 = new WebTestRequest("http://testserver/website/register.aspx");
      request4.ThinkTime = 9;
      ExtractHiddenFields rule2 = new ExtractHiddenFields();
      rule2.ContextParameterName = "1";
      request4.ExtractValues += new EventHandler<ExtractionEventArgs>(rule2.Extract);
      yield return request4;

      WebTestRequest request5 = new WebTestRequest("http://testserver/website/register.aspx");
      request5.ThinkTime = 5;
      request5.Method = "POST";
      FormPostHttpBody request5Body = new FormPostHttpBody();
      request5Body.FormPostParameters.Add("__VIEWSTATE",
this.Context["$HIDDEN1.__VIEWSTATE"].ToString());
      request3Body.FormPostParameters.Add("username",
this.Context["DataSource1.Credentials.UserName"].ToString());
      request3Body.FormPostParameters.Add("password",
this.Context["DataSource1.Credentials.Password"].ToString());
      request5Body.FormPostParameters.Add("confirmpassword",
this.Context["DataSource1.Credentials.Password"].ToString());
      request5.Body = request5Body;
      yield return request5;
    }

    // ユーザーがログイン済みになったので、ユーザーのプロファイルを見に行きます。

    WebTestRequest request6 = new WebTestRequest("http://testserver/website/userprofile.aspx");
    yield return request6;
  }
}

ループ

テスト中に判別された数の要求を動的に発行するために Web テストがループする必要のある場合に、コード化 Web テストを使用します。

これを以下の例を使用して説明します。そこでは、Web テストは、検索を実行してから、検索結果のそれぞれのリンクをたどります。

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.WebTesting;

public class LoopingCoded : WebTest
{
  public LoopingCoded()
  {
  }

  public override IEnumerator<WebTestRequest> GetRequestEnumerator()
  {
    // Microsoft という語の検索を発行します。

    WebTestRequest request7 = new WebTestRequest("http://testserver/website/Search.aspx");
    request7.ThinkTime = 20;
    request7.Method = "POST";
    FormPostHttpBody request7Body = new FormPostHttpBody();
    request7Body.FormPostParameters.Add("txtSearch", "Microsoft");
    request7.Body = request7Body;
    yield return request7;

    // 検索結果内の各アンカー タグのループをたどってから、各タグのターゲット URL (href) に対する要求を発行します。
    foreach (HtmlTag tag in this.LastResponse.HtmlDocument.GetFilteredHtmlTags("a"))
    {
      WebTestRequest loopRequest = new WebTestRequest(tag.GetAttributeValueAsString("href"));
      yield return loopRequest;
    }
  }
}

きめの細かいイベント処理

特定の要求に対してのみ PreRequest および PostRequest イベント ハンドラを適用したい場合に、コード化 Webテストを使用します。 通常の Web テストでは、WebTestRequestPlugins (両方のイベントを処理します) は、Web テスト内のすべての要求に対して適用されます。

これを以下の例を使用して説明します。そこでは、Web テストは、デバッグあるいはベースライン設定の目的で、2 つの要求の応答本体をディスクに記録します。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.VisualStudio.TestTools.WebTesting;


public class EventHandlingCoded : WebTest
{
  public EventHandlingCoded()
  {
  }

  public override IEnumerator<WebTestRequest> GetRequestEnumerator()
  {
    WebTestRequest request1 = new WebTestRequest("http://testserver/website");
    request1.ThinkTime = 8;
    yield return request1;

    // この応答をファイルに記録します。

    WebTestRequest request2 = new WebTestRequest("http://testserver/website/products.aspx");
    request2.ThinkTime = 2;
    request2.QueryStringParameters.Add("CategoryID", "14", false, false);
    request2.PostRequest += new EventHandler<PostRequestEventArgs>(request2_PostRequest);
    yield return request2;

    WebTestRequest request3 = new WebTestRequest("http://testserver/website/products.aspx");
    request3.ThinkTime = 2;
    request3.QueryStringParameters.Add("CategoryID", "15", false, false);
    yield return request3;

    // この応答も、ファイルに記録します。

    WebTestRequest request4 = new WebTestRequest("http://testserver/website/products.aspx");
    request4.ThinkTime = 1;
    request4.QueryStringParameters.Add("CategoryID", "20", false, false);
    request4.PostRequest += new EventHandler<PostRequestEventArgs>(request4_PostRequest);
    yield return request4;
  }

  void request2_PostRequest(object sender, PostRequestEventArgs e)
  {
    File.WriteAllBytes("c:\\request2.html", e.Response.BodyBytes);
  }

  void request4_PostRequest(object sender, PostRequestEventArgs e)
  {
    File.WriteAllBytes("c:\\request4.html", e.Response.BodyBytes);
  }
}

コード化 Web テストを使用した JavaScript のシミュレート

先に申し上げたとおり、Web テスト エンジンは、HTTP 層内で稼働するので、JavaScript を実行しません。 HTTP 層に影響を与えるようなやり方で JavaScript に依存する Web サイトは、コード化 Web テストを使用して、JavaScript によって通常実行される論理をシミュレートすることができます。

単純な Web ページを以下に示してあります。これは、電話番号を収集するとともに、JavaScript を使用して、フォームの送信時に特定の非数値文字を取り除きます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Untitled Page</title>
  <script type="text/javascript">
    // 電話番号文字列内にある共通した特定の非数値文字を
    // 取り除きます。
    function FixPhoneNumber() {
      var phoneNumberElement = document.getElementById('phoneNumber');
      var number = phoneNumberElement.value;
      number = number.replace('-', '');
      number = number.replace('(', '');
      number = number.replace(')', '');
      number = number.replace(' ', '');

      phoneNumberElement.value = number;

      return true;
    }
  </script>
</head>
<body>
  <form action="http://testserver/testwebsite/showparameters.aspx" method="post">
  <div>
    <input name="phoneNumber" id="phoneNumber" type="text"/>
    <input name="submit" type="submit" value="Submit" onclick="FixPhoneNumber()" />
  </div>
  </form>
</body>
</html>

この種のページのテストでは、phoneNumber フィールドを指定したデータ バインディングを使用すると、問題が起きることがあります。 正しいフォーマットの電話番号がデータ ソース内に置かれていないと、想定外のデータがサーバーに送信され、それが原因で Web テストが失敗することがあります。 JavaScript が無効になっている場合は、サーバーがデータを検証して修正するのが理想的ですが、クライアント側のスクリプトの実行をシミュレートするために、やはり Web テストが必要になることがあります。

たいていの場合、HTTP 要求に影響を与える JavaScript をコード化 Web テストは簡単にシミュレートすることができます。 以下の例は、上記の JavaScript のシミュレートを示しています。

   public override IEnumerator<WebTestRequest> GetRequestEnumerator()
    {
      WebTestRequest request1 = new WebTestRequest("http://testserver/testwebsite/default.aspx");
      yield return request1;

      WebTestRequest request2 = new WebTestRequest("http://testserver/testwebsite/showparameters.aspx");
      request2.Method = "POST";
      FormPostHttpBody request2Body = new FormPostHttpBody();

      //データ バインドの電話番号をコンテキストから取得してから、
      // 特定の文字を取り除いて JavaScript をシミュレートします。
      string phoneNumber = this.Context["PhoneNumber"].ToString();
      phoneNumber = phoneNumber.Replace("-", "");
      phoneNumber = phoneNumber.Replace("(", "");
      phoneNumber = phoneNumber.Replace(")", "");
      phoneNumber = phoneNumber.Replace(" ", "");

      request2Body.FormPostParameters.Add("phoneNumber", phoneNumber);
      request2Body.FormPostParameters.Add("submit", "Submit");
      request2.Body = request2Body;
      yield return request2;
    }

コード化 Web テストの実行およびデバッグ

コード化 Web テストを実行するには、[Test View] あるいは [Test Manager] ウィンドウでテストを選択してから、[Run] ツール バー ボタンをクリックします。 コード化 Web テストの実行が開始したら、[Test Results] ウィンドウ内をダブルクリックし、Web テスト ビューアを表示することができます。 この同じ機能を使用して、コード化 Web テストが通常の Web テストと同様に正しいことを検証することもできます。

Web テストは Visual Studio に統合されているので、以下のスクリーンショットに示されているとおり、[Run] の代わりに [Debug] を選択して、コード化 Web テストをデバッグすることができます。 コード化 Web テスト内のどこにでもブレークポイントを置くことができ、標準のデバッグ メカニズムはすべて使用可能です。

ms364082.webtesttechniques02(ja-jp,VS.80).gif

図 6

まとめ

Visual Studio 2005 Team Edition for Tester での Web テストの作成、検証、およびデバッグのご理解が深まったなら、それは喜ばしいことです。  その他の情報およびサポート リソースは、Web テストのオンライン ドキュメントブログ (英語)、およびチームのMSDN サポート フォーラム (英語)に掲載されています。

著者の紹介

Josh Christie は、Visual Studio Team System Web チームおよび Load Testing チームに所属するソフトウェア デザイナ エンジニアです。 同氏は主に、Web テスト エンジン、コード化 Web テスト、およびブラウザ レコーダに携わっています。 Web テストの詳細は、http://blogs.msdn.com/joshch/ (英語) の同氏のブログを参照してください。

この情報は役に立ちましたか。
(残り 1500 文字)