印刷用ページ       送信     
クリックして評価とフィードバックをお寄せください
 テストの実行: Windows PowerShell を使用した要求/...
Related Articles

XNA Game Studio 3.0 を使用して Zune 用のゲームを作成するための基本事項について Mike Calligaro が説明します。

Mike Calligaro

MSDN Magazine May 2009

...

Read more!

今月は、AJAX アプリケーションでフォームを使用するケースについて説明し、自動保存、JIT 検証、送信回数の削減などの機能を実装するさまざまな方法を紹介します。

Dino Esposito

MSDN Magazine June 2009

...

Read more!

メモリ使用量はアプリケーションの実行速度に直接影響を及ぼす可能性があるため、最適化する必要があります。この記事では、.NET プログラムを対象に、メモリの最適化の基本について説明します。

Subramanian Ramaswamy および Vance Morrison

MSDN Magazine June 2009

...

Read more!

Azure Services Platform に含まれる .NET Services を使用するとワークフロー アプリケーションをクラウドに簡単に移行できることを解説します。

Aaron Skonnard

MSDN Magazine April 2009

...

Read more!

Microsoft Velocity は、統一された分散メモリ キャッシュをクライアント アプリケーションで使用できるように公開します。この記事では、Velocity をデータ ドリブン アプリケーションに追加する方法を説明します。

Aaron Dunnington

MSDN Magazine June 2009

...

Read more!

Also by this Author

ここでは、タイミング、コスト、およびその他の潜在的なリソース不足に関連するソフトウェア プロジェクトのリスクを見積もるために、James McCaffrey がいくつかの統計的手法と彼が PERIL と呼んでいる手法を使用します。

Dr. James McCaffrey

MSDN Magazine January 2009

...

Read more!

ここでは、Windows PowerShell を使用して、ASP.NET および従来の ASP Web アプリケーション用にすばやく簡単な UI テスト自動化を作成する方法を紹介します。

Dr. James McCaffrey

MSDN Magazine March 2008

...

Read more!

今月のコラムでは、James McCaffrey 博士が、Visual Studio 2005 Team System を使用してカスタム ソフトウェアのテスト自動化を管理する方法について説明します。

Dr. James McCaffrey

MSDN Magazine Launch 2008

...

Read more!

今月のコラムでは、James McCaffrey が優れたソフトウェア テスト担当者に求められる資質とスキルについて説明します。

Dr. James McCaffrey

MSDN Magazine December 2008

...

Read more!

今月は、IronPython を使用して .NET ベースのライブラリを簡単にテストできることを実演します。

James McCaffrey

MSDN Magazine June 2009

...

Read more!

Popular Articles

ここでは、新しい F# 言語の基になるいくつかの概念について説明します。F# 言語は、関数型 .NET 言語とオブジェクト指向 .NET 言語の両方の要素を持っています。また、単純なプログラムを記述する方法についても説明します。

Ted Neward

MSDN Magazine Launch 2008

...

Read more!

SQL Server 2005 で正規表現を使用して、効率的で高度なテキスト分析を実行できます。

David Banister

MSDN Magazine February 2007

...

Read more!

James Avery does it again with his popular list of developer tools. This time he covers the best Visual Studio add-ins available today that you can download for free.

James Avery

MSDN Magazine December 2005

...

Read more!

C# allows developers to embed XML comments into their source files-a useful facility, especially when more than one programmer is working on the same code. The C# parser can expand these XML tags to provide additional information and export them to an external document for further processing. This article shows how to use XML comments and explains the relevant tags. The author demonstrates how to set up your project to export your XML comments into convenient documentation for the benefit of other developers. He also shows how to use comments ...

Read more!

Writing a Web application with ASP.NET is unbelievably easy. So many developers don't take the time to structure their applications for great performance. In this article, the author presents 10 tips for writing high-performance Web apps. The discussion is not limited to ASP.NET applications because they are just one subset of Web applications.

Rob Howard

MSDN Magazine January 2005

...

Read more!

テストの実行
Windows PowerShell を使用した要求/応答テスト
Dr. James McCaffrey

コードのダウンロード : : TestRun2008_05.exe (152 KB)
Browse the Code Online
最も基本的な形式の Web テストは HTTP 要求/応答テストです。このテストでは、プログラムを使用して HTTP 要求を Web アプリケーションに送信し、HTTP 応答を取得し、期待値との比較によって応答を検証します。
ASP.NET アプリケーションの要求/応答テストを実行するには、いくつかの方法があります。まず、C# または Visual Basic® でコンソール アプリケーションを作成するという方法があります。JavaScript スクリプトまたは Perl スクリプトを作成することもできます。困難な仕事に取り組みたいなら、C/C++ プログラムを作成してもよいでしょう。さらに、最近は Windows PowerShell™ も利用できます。
これらの方法はほとんど試しましたが、私としては軽量の HTTP 要求/応答テストには Windows PowerShell を使用する方法をお勧めします。Web サーバー上の ASP.NET アプリケーションに情報を送信する小さな Windows PowerShell スクリプトを作成するだけです。このスクリプトで HTTP 応答を取得し、期待値と比較して、合格か不合格かを判定できます。
今月のコラムでは、Windows PowerShell を使用して ASP.NET アプリケーションの要求/応答テストを実行する方法を説明します。この記事の内容は、ASP.NET と Windows PowerShell について少なくとも基礎的な知識がある読者を対象としています。ただし、そうした基礎知識がない場合でも、それほど苦労することなく理解できると思います。
図 1 は、MiniCalc という簡素ながら典型的な ASP.NET Web アプリケーションを示しています。ご覧のとおり、MiniCalc は 2 つの整数を受け取り、和または積を求め、結果を小数点以下 4 桁までの数値として表示します。実際の Web アプリケーションはこのサンプルよりはるかに複雑ですが、ここで説明する手法は複雑なアプリケーションにも簡単に応用できます。
図 1 テスト用の簡単な ASP.NET Web アプリケーション (画像を拡大するには、ここをクリックします)
図 2 は、私が作成した Windows PowerShell テスト スクリプトの実行中の画面です。わかりやすくするために、テストするアプリケーションの情報をすべてハードコーディングしました。このスクリプトをパラメータ化する方法については後で説明します。このスクリプトは、まず対象とする URL の http://localhost/MiniCalc/Default.aspx をエコーし、次に Web アプリケーションの ViewState および EventValidation の初期値に対する調査要求を実行します。これらはキー値です。これについては後ほど説明します。
図 2 実行中の Windows PowerShell テスト スクリプト (画像を拡大するには、ここをクリックします)
次に、このスクリプトは、ユーザーによる TextBox1 への 5 の入力、TextBox2 への 3 の入力、RadioButton1 の選択 (加法演算の指定)、そして Button1 のクリック (計算の開始) をシミュレートする情報を送信します。さらに、Web サーバーから HTTP 応答を取得し、応答全体を表示し、その応答を調べて、計算結果の表示を目的として作成されたコントロール TextBox3 に 8.0000 (5 + 3 の結果) が含まれていることを確認します。

テスト用アプリケーション
このテスト自動化の対象は MiniCalc という簡単な Web アプリケーションです。このアプリケーションは、2008 年 3 月号のコラムで初めて紹介しました (msdn2.microsoft.com/magazine/cc337896.aspx をご覧ください)。この Web アプリケーション MiniCalc の完全なコードを図 3 に示します。
<%@ Page Language="C#" %>
<script language="C#" runat="server">
  private void Button1_Click(object sender, System.EventArgs e)
  {
    int alpha = int.Parse(TextBox1.Text.Trim());
    int beta = int.Parse(TextBox2.Text.Trim());
    
    if (RadioButton1.Checked) {
      TextBox3.Text = Sum(alpha, beta).ToString("F4");
    }
    else if (RadioButton2.Checked) {
      TextBox3.Text = Product(alpha, beta).ToString("F4");
    }
    else
      TextBox3.Text = "Select method";
  }
  private static double Sum(int a, int b) {
    double ans = a + b;
    return ans;
  }
  private static double Product(int a, int b) {
    double ans = a * b;
    return ans;
  }
</script>

<html>
  <head>
    <style type="text/css">
      fieldset { width: 16em }
      body { font-size: 10pt; font-family: Arial }
    </style>
    <title>Default.aspx</title>
  </head>
  <body bgColor="#ccffff">
    <h3>MiniCalc by ASP.NET</h3>
    <form method="post" name="theForm" id="theForm" runat="server"
       action="Default.aspx"> 
      <p><asp:Label id="Label1" runat="server">
         Enter integer:&nbsp&nbsp</asp:Label>
        <asp:TextBox id="TextBox1" width="100" runat="server" />
      </p>
      <p><asp:Label id="Label2" runat="server">
          Enter another:&nbsp</asp:Label>
         <asp:TextBox id="TextBox2" width="100"  runat="server" />
      </p>
      <fieldset>
        <legend>Arithmentic Operation</legend>
        <p><asp:RadioButton id="RadioButton1" GroupName="Operation"
            runat="server"/>Addition</p>
        <p><asp:RadioButton id="RadioButton2" GroupName="Operation" 
            runat="server"/>Multiplication</p>
        <p></p>
      </fieldset>
      <p><asp:Button id="Button1" runat="server" text=" Calculate "
        onclick="Button1_Click" /> </p>
      <p><asp:TextBox id="TextBox3" width="120"  runat="server" /></p>
    </form>
  </body>
</html>

このソース コードで最も重要な部分は ASP.NET サーバー コントロールの ID です。ここでは、Label1 (ユーザー プロンプト)、TextBox1 および TextBox2 (2 つの整数の入力)、RadioButton1 および RadioButton2 (加算または乗算の選択)、Button1 (計算)、TextBox3 (結果) という既定の ID を使用しています。ASP.NET アプリケーションに対して自動化された HTTP 要求/応答テストを実行するには、そのアプリケーションのコントロールの ID がわかっている必要があります。また、私のテスト アプリケーションの ID はダウンロード可能なソース コードで確認できますが、他の人が作成した Web アプリケーションをテストする場合でも、Internet Explorer® で [表示] メニューの [ソース] をクリックし、そのアプリケーションのソースを表示することにより、ID を調べることができます。
<form> 要素の action 属性は Default.aspx に設定されています。ユーザーが要求を送信するたびに、同じ Default.aspx コードが実行されます。HTTP はステートレスなプロトコルであるため、ASP.NET はアプリケーションの状態を ViewState と呼ばれる非表示の値に保持することによってステートフルなアプリケーションにするという効果をもたらします。
ViewState 値は Base64 でエンコードされた文字列であり、複数の要求/応答ラウンドトリップにわたって ASP.NET ページの状態を保持します。ASP.NET では、非表示の入力コントロールを使用して ViewState を保持します。同じように、ASP.NET 2.0 には、スクリプト挿入攻撃を防止するセキュリティ目的の EventValidation 値が追加されました。この 2 つのメカニズムは、プログラムを使用して ASP.NET 2.0 Web アプリケーションにデータを送信する際に重要な役割を果たします。

基本的な ASP.NET 要求/応答テスト
図 2 のスクリーンショットを生成した Windows PowerShell スクリプトには、ASP.NET Web アプリケーションを対象とする基本的な HTTP 要求/応答テストの実行に必要な手法がすべて含まれています。また、このスクリプトを基礎として、より高度なテストを実行するスクリプトを作成することもできます。
注意していただきたいのは、このスクリプトは現在のディレクトリにありますが、セキュリティ上の理由からスクリプトの保存場所を指定する必要があることです (単に test.ps1 とするのではなく .\test.ps1 と指定します)。また、Windows PowerShell では、スクリプトの実行が既定で許可されていないことにも注意してください。スクリプトの実行を有効にするために、前の Windows PowerShell セッションで Set-ExecutionPolicy unrestricted コマンドを入力しています。この PowerShell 実行ポリシーは、明示的に変更されるまで、同じユーザーにおいて、以降のすべてのシェル インスタンスおよびユーザー セッションで有効になります。
test.ps1 スクリプト全体の構造は、次のようになります。
# file: test.ps1
function main()
{
  # send request, get response, check response
}
function getVSandEV($url)
{
  # get initial ViewState and EventValidation values
}
main
# end script
最初の行は Windows PowerShell コメントです。その後に作業のほとんどの部分を実行する main 関数があり、さらにヘルパ関数 getVSandEV があります (このヘルパ関数については、後で詳しく説明します)。"main" 関数の使用は必須ではありません。また、main は予約語ではないため、別の識別子を使用することもできます。
Windows PowerShell はスクリプトの構成の点できわめて柔軟性に富んでいます。プログラム定義の関数をまったく使用しないのであれば、このスクリプトのコードをすべて test.ps1 に入れることができます。また、追加のヘルパ関数を記述して main 関数を分割することもできます。
このスクリプトの最後から 2 行目に注目してください。main は定義済みのプログラム エントリ ポイントではないため、main 関数を明示的に呼び出す必要があります。
この main 関数は次のステートメントで始まっています。
$url = "http://localhost/MiniCalc/Default.aspx"
このステートメントは変数 $url に文字列値を割り当てます (厳密に言うと、$url はオブジェクトですが、単純な Windows PowerShell オブジェクトを変数として扱うことが許容されています)。Windows PowerShell の変数名は "$" で始まるため、スクリプト内で変数を簡単に見分けられます。
Windows PowerShell スクリプト言語は明示的に型指定された言語であり、型の推定をサポートしています。明示的に型指定されていない Windows PowerShell 変数がある場合は、Windows PowerShell 実行エンジンによって型が推定されます。この例では、変数 $url は値が二重引用符で囲まれていることから文字列変数と解釈されます。次のように、明示的な型修飾子を指定することもできます。
   [string] $url = `
     "http://localhost/MiniCalc/Default.aspx"
Windows PowerShell は Microsoft® .NET Framework を基礎としているため、すべての .NET 型 (Int32 や String など) またはそれらに対応する C# マッピング エイリアス (int や string など) を使用できます。変数に明示的な型を追加すると、ある程度のランタイム エラー チェックが可能となり、可読性も向上します。ただ、その分だけ記述量が増加します。
2 つ目のステートメントは、次のようにメッセージをシェルに出力します。
   write-host `
      "`nWeb Application under test is: " $url
ここでは、Write-Host コマンドレットを使用してメッセージを表示しています。Windows PowerShell では、文字列に一重引用符と二重引用符の両方が使用されます。私は二重引用符を使用しているので、Windows PowerShell で "改行" 文字を意味する `n シーケンスを文字列に挿入することができます (一重引用符で囲まれた文字列はリテラルと見なされます)。

ヘルパ関数の内容
次に、プログラム定義の関数を呼び出して、MiniCalc Web アプリケーションの ViewState および EventValidation の初期値を調べます。
$vs,$ev = getVSandEV($url)
ここでは、getVSandEV 関数の 2 つの戻り値を変数 $vs および $ev に割り当てています (後で説明するように、この関数の戻り値は実際には 2 つの値が含まれる 1 つの配列です)。
getVSandEV ヘルパ関数の全体を図 4 に示します。getVSandEV 関数は、指定された ASP.NET Web ページの ViewState および EventValidation の初期値を返します。入力パラメータ $url に型は指定していませんが、ランタイム エラー チェックを行えるように明示的に型を指定することもできます。
function getVSandEV($url)
{
  $wc = new-object net.WebClient
  $probe = $wc.downloadData($url)
  $s = [text.encoding]::ascii.getString($probe)

  $start = $s.indexOf('id="__VIEWSTATE"', 0) + 24
  $end = $s.indexOf('"', $start)
  $vs = $s.substring($start, $end-$start)

  write-host "`nInitial ViewState is: " $vs

  $start = $s.indexOf('id="__EVENTVALIDATION"', 0) + 30
  $end = $s.indexOf('"', $start)
  $ev = $s.substring($start, $end-$start)

  write-host "`nInitial EventValidation is: " $ev

  return ($vs,$ev)
}

getVSandEV の最初の行は、次のように WebClient オブジェクトをインスタンス化します。
$wc = new-object net.WebClient
ここでは、new-object コマンドレットを使用して WebClient オブジェクトを作成しています (WebClient クラスは System.Net 名前空間に属しています)。この場合も次のように $wc オブジェクトの型を明示的に指定できます。
[net.WebClient] $wc = new-object net.WebClient
WebClient クラスでは、HTTP 要求の送信とそれに対する HTTP 応答の取得を簡単に行うことができます。この操作は、次のような 1 つのステートメントだけで実行できます。
$probe = $wc.downloadData($url)
WebClient クラスの DownloadData メソッドを呼び出しています。このメソッドの戻り値は、指定された URL にあるアプリケーションからの HTTP 応答全体が含まれるバイト配列です。この応答を $probe というバイト配列に格納しています。この配列についても、[byte[]] $probe のように明示的に型を指定できます。次に、HTTP 応答をバイト配列から文字列に変換します。
$s = [text.encoding]::ascii.getString($probe)
この構文は一見すると少し込み入っています。text.encoding は System.Text 名前空間の Encoding クラスです。ascii は Encoding クラスの静的プロパティで、getString はメソッドです。ここではバイト配列を 1 ステップで文字列に変換していますが、次のように 2 つのステップで行うこともできます。
$e = [text.encoding]::ascii
$s = $e.getString($probe)

ViewState と EventValidation を抽出する
この時点で、変数 $s には HTTP 応答の全体が文字列として格納されています。この文字列は ViewState 値を含み、次のような構造をしています。
<input type="hidden" name="__VIEWSTATE"
 id="__VIEWSTATE" value="/wEPDwUK ... Bbzmv" />
ここで、$s から ViewState 値を抽出する必要があります。次のように、ViewState 値の先頭を示す $s 内のインデックス位置を指定しています。
$start = $s.indexOf('id="__VIEWSTATE"', 0) + 24
ご覧のとおり、IndexOf メソッドを使用して文字列 id="__VIEWSTATE" を検索しています。引数 0 は、検索を $s 内のインデックス位置 0 (応答の文字列の開始位置) から始めることを意味します。対象の文字列を一重引用符で囲んでいるのは、文字列に二重引用符が含まれているためです。対象の文字列がどこから始まるかがわかれば、そのインデックスから 24 文字目が実際の ViewState 値の開始位置となります ("__VIEWSTATE" の先頭のアンダースコアは 1 つではなく 2 つであることに注意してください)。
このように ViewState の初期値の解釈方法はいたって簡素なものなので、コードの脆弱化をもたらします。ただ、このスクリプトはテスト自動化を迅速かつ容易に行うことを主眼に置いています。また、このスクリプトはすばやく簡単に変更できるので、ビュー ステートの格納形式が異なるためにコードが動作しなくなったとしても対応は可能です。
次に、ViewState 値が $s 内のどこで終わっているかを調べます。
$end = $s.indexOf('"', $start)
ViewState 値の先頭より後で最初に出現する二重引用符を検索し、その位置を変数 $end に格納しています。ViewState 値の応答文字列 $s における開始位置と終了位置がわかったので、この値を SubString メソッドで抽出することができます。
$vs = $s.substring($start, $end-$start)
write-host "`nInitial ViewState is: " $vs
SubString メソッドには、引数として、$s 内の抽出の開始位置を示すインデックスと抽出する文字数 (間違えやすいですが、抽出の終了位置を示すインデックスではありません) を渡します。この時点で、変数 $vs には対象とするページの ViewState の初期値が格納されています。EventValidation 値も次のように同じ方法で抽出できます。
$start = $s.indexOf('id="__EVENTVALIDATION"', 0) + 30
$end = $s.indexOf('"', $start)
$ev = $s.substring($start, $end-$start)
write-host "`nInitial EventValidation is: " $ev
ここでは、変数 $start および $end を再利用しています。ViewState 値の場合と異なる点は、応答文字列 $s 内の EventValidation 値の開始位置が id= "__EVENTVALIDATION" 文字列の先頭から 30 文字目であることだけです。
次に、$vs と $ev の 2 つの値を getVSandEV 関数によって返す必要があります。そのために、ここでは単純ながら強力な次の Windows PowerShell 関数を使用しました。
return ($vs,$ev)
かっこは Windows PowerShell 配列を示しています。また、Windows PowerShell はパイプライン アーキテクチャに基づいているため、キーワード return を省略することもできます。ここでは、馴染み深いプログラミング手法であるため、わかりやすくするために "return" を使用しています。

ViewState 値と EventValidation 値を操作する
ここで、再び test.ps1 スクリプトの main 関数に戻ります。次のステートメントは以下の 3 つです。
[Reflection.Assembly]::LoadFile( `
  'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll')`
  | out-null

$vs = [System.Web.HttpUtility]::UrlEncode($vs)
$ev = [System.Web.HttpUtility]::UrlEncode($ev)
ViewState 値と EventValidation 値は、いずれも Base64 でエンコードされた文字列です。Base64 エンコードでは、大文字の A ~ Z、小文字の a ~ z、数字の 0 ~ 9、+、/ という 64 の文字を使用します (Base64 ではパディングに = を使用します)。これらの文字には HTTP 要求ストリームで使用できないものもあるため、ViewState 値と EventValidation 値に対して UrlEncode 操作を実行する必要があります。
UrlEncoding は、問題となる可能性のある文字を % で始まる 3 文字のシーケンスに変換します。たとえば、未加工の > 文字は %3D とエンコードされ、空白は %20 とエンコードされます。Web サーバーは、これらの特殊な 3 文字のシーケンスを含む HTTP 要求を受け取ると、そのシーケンスを未加工の入力にデコードします。
.NET Framework には、System.Web アセンブリの HttpUtility クラスに属する静的メソッド UrlEncode があります。ただし、多くの .NET 名前空間とは異なり、Windows PowerShell は既定では System.Web にアクセスできません。そのため、UrlEncode を使用するためには、事前に System.Web アセンブリを読み込む必要があります。これを行うために、System.Reflection 名前空間の静的メソッドである LoadFile を使用し、それを out-host コマンドレットにパイプして、System.Web の読み込みから登録までの間に煩わしい進行状況メッセージが表示されないようにしています。
これで、送信データの準備に移ることができます。HTTP 送信データは、次のようにアンパサンド文字で連結された名前と値のペアのセットです。
$postData = `
  'TextBox1=5&TextBox2=3&Operation=RadioButton1&Button1=clicked'
write-host "`nPosting: " $postData
送信文字列の名前と値のペアのうち最初の 2 つについては、説明はまったく不要でしょう。TextBox1 を 5、TextBox2 を 3 にそれぞれ設定しているだけです。3 つ目の名前と値のペア Operation=RadioButton1 は、ユーザーによる RadioButton コントロール (ここでは加算に対応する RadioButton) の選択をシミュレートしています。ラジオ ボタンを設定するには RadioButton1=checked のような構文を使用すると勘違いした人もいるかもしれません (私も初めはそうでした)。しかし、RadioButton1 は Operation コントロールの値であってコントロールそのものではありません。
4 つ目の名前と値のペア Button1=clicked は誤解を招きやすいところがあります。Button1 の値を渡し、このボタンのクリックをシミュレートする必要がありますが、値はどのようなものでもかまいません。Button1=foo を使用することもできます (さらに Button1= とすることも可能です) が、わかりやすくするために Button1=clicked としました。
次に、Url でエンコードされた ViewState 値と EventValidation 値を送信データに追加し、バイト配列に変換します。
$postData += '&__VIEWSTATE=' + $vs
$postData += '&__EVENTVALIDATION=' + $ev
$buffer = [text.encoding]::ascii.getbytes($postData)
Windows PowerShell は、文字列を連結する手段として馴染み深い += 演算子をサポートしています。これらの文字列はいずれも先頭に 2 つのアンダースコアがあることに注意してください。GetBytes メソッドは、文字列を受け取り、それをバイトの配列として返します。
ここで、次のように HttpWebRequest オブジェクトを作成します。
[net.httpWebRequest] $req = [net.webRequest]::create($url)
$req.method = "POST"
$req.ContentType = "application/x-www-form-urlencoded"
$req.ContentLength = $buffer.length
$req.TimeOut = 5000
HttpWebRequest オブジェクトを作成するには、明示的な Create メソッドを使用します。Create は System.Net.WebRequest クラスに属していることに注意してください。この点は混乱を招く可能性があるため、$req オブジェクトには明示的に型 ([Net.HttpWebRequest]) を指定しました。
次の 4 行では、HttpWebRequest オブジェクトを作成するために、型 (POST)、コンテンツの種類 (application/ x-www-form-urlencoded)、コンテンツの長さ (実行時に計算)、およびサーバーのタイムアウト値 (5000、これは 5,000 ミリ秒、つまり 5 秒を意味します) を指定しています。ここで、次のように HTTP 要求を MiniCalc Web アプリケーションに送信します。
$reqst = $req.getRequestStream()
$reqst.write($buffer, 0, $buffer.length)
$reqst.flush()
$reqst.close()
HttpWebRequest クラスには Send メソッドがありません。そのため、HttpWebRequest オブジェクトから要求ストリーム オブジェクトを作成し、そのストリームに書き込んでいます。Write メソッドは要求を準備するだけです。その HTTP 要求を実際に送信するのは Flush メソッドです。Close メソッドは自動的に Flush 操作を実行するため、$reqst.flush() ステートメントを省略することもできます。
今度は、次のように HTTP 応答を取得する必要があります。
[net.httpWebResponse] $res = $req.getResponse()
$resst = $res.getResponseStream()
$sr = new-object IO.StreamReader($resst)
$result = $sr.ReadToEnd()
write-host "`nHTTP Response is " $result 
これらの行では、まず HttpWebRequest オブジェクト ($req) から HttpWebResponse オブジェクト ($res) を作成しています。ここでは、わかりやすくするために型を指定しました。次に、System.IO.Stream オブジェクト ($resst) を作成しています。さらに、応答ストリームを処理するための StreamReader オブジェクトを作成し、ReadToEnd メソッドを使用して HTTP 応答全体を文字列として取得し、変数 $result に格納しています。このプログラミング パラダイムは初めのうちは少し面倒に感じるかもしれませんが、数回も使用すれば慣れてきます。
HTTP 応答を取得したので、次のように期待値と比較して検証することができます。
write-host "`nLooking for 8.000"
if ($result.indexOf('value="8.0000"') -ge 0) {
  write-host "`nFound 8.0000 -- Test scenario Pass`n" `
    -foregroundcolor green
}
else {
  write-host "`nDid not find 8.0000 -- Test scenario FAIL`n" `
    -foregroundcolor red
}
String.IndexOf メソッドを使用して TextBox3 で value=8.0000 を検索します (5 + 3 と等しいデータを送信したからです)。Windows PowerShell は -ge (>= ではない) や -eq (== ではない) などの Boolean 比較演算子を使用することに注意してください。このテスト自動化スクリプトの最後の 2 行は、リソースをクリーンアップします。
$sr.close()
$resst.close()
StreamReader オブジェクトとそれに関連する要求ストリームを閉じているだけです。もちろん、この処理はもっと早い段階 (合格/不合格を判定する前) に実行することもできます。

要求/応答自動化を拡張する
これまでに説明してきたことは、いずれも ASP.NET Web アプリケーションの軽量 HTTP 要求/応答テストを実行するために必要となる基本的な手法です。このコードをさまざまな方法で拡張し、簡単なテスト ハーネスを作成することができます (図 5 を参照)。
図 5 簡単なテスト ハーネス (画像を拡大するには、ここをクリックします)
Windows PowerShell スクリプトをパラメータ化することもできます。ここで紹介した例では、対象とするアプリケーションの URL をスクリプトにハードコーディングしましたが、URL をコマンド ラインから受け取るようにスクリプトを書くことができます。
   #file: harness.ps1
   param($url = $(throw "URL required"))
   (etc.)
その場合、スクリプトは次のように呼び出します。
   PS C:\MyScripts> .\harness.ps1 `
    'http://localhost/MiniCalc/Default.aspx'
param ステートメントを使用する場合は、Windows PowerShell スクリプトでコメントを除いて最初のステートメントとする必要があります。throw ステートメントがあることによって、コマンド ライン引数が必須になります。引数を省略すると、スクリプトは例外をスローします。
テスト ケース データをパラメータ化することもできます。簡単なアプローチの 1 つとして、テスト ケース データをスクリプト内の次のような配列に入れるという方法があります。
$cases = (
  ('0001,TextBox1=5&TextBox2=3&Operation=' +
    'RadioButton1&Button1=clicked,value="8.0000"'),
  ('0002,TextBox1=5&TextBox2=3&Operation=' +
    'RadioButton2&Button1=clicked,value="15.0000"'),
  ('0003,TextBox1=0&TextBox2=0&Operation=' +
    'RadioButton1&Button1=clicked,value="0.0000"')
)
@ によって、変数 $cases が配列型になります。ただし、@ は実際には省略できます。この場合はあいまいになるおそれがないからです。次のように、個々のテスト ケースについて同じ方法で指定できます。
foreach ($case in $cases) {
  $caseID,$input,$expected = $case.split(",")
  # get ViewState and EventValidation values
  # construct post data
  # send HTTP request, get response
  # determine pass/fail
}
foreach ループは、配列 $cases から文字列を 1 つずつ順に抽出し、現在の文字列を $case に格納します。次に、split メソッドが現在の文字列をコンマの位置で分割し、その結果を変数 $caseID、$input、および $expected に格納します。
Windows PowerShell には、例外を処理する trap ステートメントなど、いくつものエラー処理機能が用意されています。たとえば、テスト自動化では、通常、あるテスト ケースで例外が発生してもハーネスの実行を継続する必要があります。その場合、Windows PowerShell では trap ステートメントと continue ステートメントを使用します。
function main(){
  # test cases here
  foreach ($case in $cases) {
    # run test case
    trap {
      write-host "Fatal exception caught!"
      continue
    }
  }
}
もちろん、合格したテスト ケース数と不合格となったテスト ケース数の追跡やテスト結果の外部ファイルまたはデータベースへの書き込みなど、他にもさまざまな変更を加えることができます。

ご意見やご質問は、James まで英語でお送りください。 testrun@microsoft.com.


Dr. James McCaffrey は、Volt Information Sciences, Inc. で、マイクロソフトのソフトウェア エンジニア向けの技術トレーニングを担当しています。これまでに、Internet Explorer、MSN サーチなどの複数のマイクロソフト製品にも携わってきました。また、『.NET Test Automation Recipes』の著者でもあります。James の連絡先は jmccaffrey@volt.com または v-jammc@microsoft.com です。

Page view tracker