HttpUnitの動作コード
LoginTest#setUp()
サーバーとのやり取りを管理するクラスWebConversation
を初期化します。各テストメソッドで使用するため、このメソッドで一度だけ行うようにします。
import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; public class LoginTest extends TestCase { WebConversation wc; protected void setUp() throws Exception { super.setUp(); wc = new WebConversation(); }
LoginTest#testErrorID()
ログイン画面で、ログインIDを誤って入力した場合のテストケースです。
/** * 存在しない ログイン ID の入力 * * @throws MalformedURLException * @throws IOException * @throws SAXException */ public void testErrorID() throws MalformedURLException, IOException, SAXException { // (1) // 初期画面表示 // ------------------------------------------------------------ WebRequest request = new GetMethodWebRequest( "http://localhost:8080/httpunitapp/login.jsp"); WebResponse response = wc.getResponse(request); // ID 入力値 String wrongID = "aaa"; // (2) // 入力フォーム WebForm form = response.getForms()[0]; form.setParameter("loginID", wrongID); // (3) // 送信実行 form.submit(); // 遷移後の画面 // ------------------------------------------------------------ response = wc.getCurrentPage(); //System.out.println(response.getText()); // テスト実施 // (4) // 遷移画面 ID String sid = response.getHeaderField("X-CZ-SID"); assertEquals(sid, "SCZ001"); // (5) // メッセージコード HTMLElement elem = response.getElementWithID("msgCode"); String msgCode = elem.getText(); assertEquals(msgCode, "2"); // (6) // 前回入力した値が再表示されていること form = response.getForms()[0]; String loginID = form.getParameterValue("loginID"); assertEquals(loginID, wrongID); }
まずはログイン画面を起動する必要があります。HTTP GETをエミュレートするためにGetMethodWebRequest
クラスをインスタンス化し、サーバーへのリクエストオブジェクトを作成します。そして、そのオブジェクトを使用して、実際にサーバーへの要求を行います。setUp()
で初期化したオブジェクトwc
を使用したwc.getResponse(request)
がそれに当たります。
実行結果として、レスポンスを表すWebResponse
オブジェクトが返ってきます(1)。このオブジェクトを操作して、あたかもブラウザを実際に操作しているかのように、画面内のフォームへと値を設定していきます。
まず、画面の入力フォームを特定します。
WebResponse#getForms()
でフォームを取得できますが、HTMLでは複数のフォームが定義できるため、配列で返ってくるようなインターフェイスとなっています。今回は入力フォームが1つのみなので、配列位置は「0」としてフォームオブジェクトを取得します。そして、画面で入力するログインIDをWebForm#setParameter()
で設定します(2)。
その後、WebForm#submit()
メソッドを実行すると、通常のHTMLでのsubmitボタンを押下した時と同様の動作となり、サーバーへリクエストが送信されます(3)。
リクエスト送信後、今度はその結果に応じた画面を操作します。
WebConversation#getCurrentPage()
で、遷移後の画面の内容が取得できます。先のgetResponse()
と同様にWebResponse
のオブジェクトが返ってくるので、同様にHTML画面内を操作できます。
このメソッドでは、誤ったログインIDを入力しているので、以下のテスト項目を実施します。
- ログイン完了画面ではなく、ログイン画面に遷移している
- ログインIDのエラーなので、メッセージコードは「2」となっている
- 先ほど入力した誤ったIDがテキストボックスに表示されている
まずa.ですが、画面識別を行うためのIDはレスポンスヘッダに入れる仕様にしているので、WebResponse#getHeaderField()
でヘッダフィールド名を指定し、その値を取得します。それをJUnitのメソッドで評価します(4)。
次にb.ですが、メッセージコードの値を格納するタグはmsgCode
というHTMLのタグidでJSPに記述しています(メッセージのテキストは画面に表示しますが、メッセージコードは表示しません)。
JavaScriptを記述する際、getElementById
という関数を使う機会があるかもしれません。これと同様の動作をするメソッドとして、WebResponse#getElementWithID()
があり、idの値がmsgCode
のタグを特定できます。その上でHTMLElement#getText()
を使用し、タグの中の値を取得して評価します(5)。
最後のc.です。フォームのテキストボックス入力値をチェックします。WebForm#getParameterValue()
のパラメータとしてinput
タグのname
属性の値を指定することにより、そのタグのvalue
属性値を得ることができます。先の(2)で入力した値と一致するかを評価します。(6)
LoginTest#testErrorPWD()
このメソッドでは、入力したログインIDに対して、パスワードが誤っている場合のテストケースを実行します。
/** * 誤ったパスワードの入力 * * @throws MalformedURLException * @throws IOException * @throws SAXException */ public void testErrorPWD() throws MalformedURLException, IOException, SAXException { // 初期画面表示 // ------------------------------------------------------------ WebRequest request = new GetMethodWebRequest( "http://localhost:8080/httpunitapp/login.jsp"); WebResponse response = wc.getResponse(request); // ID 入力値 String id = "abc"; String wrongPWD = "aaa"; //(1) // 入力フォーム WebForm form = response.getForms()[0]; form.setParameter("loginID", id); form.setParameter("loginPWD", wrongPWD); // 送信実行 form.submit(); // 遷移後の画面 // ------------------------------------------------------------ response = wc.getCurrentPage(); //System.out.println(response.getText()); // テスト実施 // 遷移画面 ID String sid = response.getHeaderField("X-CZ-SID"); assertEquals(sid, "SCZ001"); //(2) // メッセージコード HTMLElement elem = response.getElementWithID("msgCode"); String msgCode = elem.getText(); assertEquals(msgCode, "3"); // 前回入力した値が再表示されていること form = response.getForms()[0]; String loginID = form.getParameterValue("loginID"); assertEquals(loginID, id); }
基本的な流れは、先のtestErrorID()
と同様です。パスワードの入力が追加となっている点と(1)、パスワードの誤りを示すメッセージコードとなっている点(2)、に差異があるだけです。
LoginTest#testLoginComplete()
ログインが正常に完了したテストケースです。
/** * ログイン正常終了 * * @throws MalformedURLException * @throws IOException * @throws SAXException */ public void testLoginComplete() throws MalformedURLException, IOException, SAXException { // 初期画面表示 // ------------------------------------------------------------ WebRequest request = new GetMethodWebRequest( "http://localhost:8080/httpunitapp/login.jsp"); WebResponse response = wc.getResponse(request); // ID 入力値 String id = "bbc"; String pwd = "yyy"; // 入力フォーム // 1つのみの入力フォームなので、配列位置は「0」 WebForm form = response.getForms()[0]; form.setParameter("loginID", id); form.setParameter("loginPWD", pwd); // 送信実行 form.submit(); // 遷移後の画面 // ------------------------------------------------------------ response = wc.getCurrentPage(); //System.out.println(response.getText()); // テスト実施 // (1) // 遷移画面 ID String sid = response.getHeaderField("X-CZ-SID"); assertEquals(sid, "SCZ002"); // (2) // メッセージコード HTMLElement elem = response.getElementWithID("msgCode"); String msgCode = elem.getText(); assertEquals(msgCode, "0"); // (3) // ユーザー情報 // 1つのみのテーブルなので、配列位置は「0」 String[][] cell = response.getTables()[0].asText(); // (4) // セル位置は「縦×横」となっており、ゼロスタート assertEquals(cell[0][1], "bbc"); assertEquals(cell[1][1], "伊藤"); assertEquals(cell[2][1], "神奈川県"); assertEquals(cell[3][1], "22"); }
今までのエラーのケースと違い、遷移先の画面が変わりますが、画面IDのチェックと、メッセージコードのチェックの仕方自体は変わりません(1)(2)。
大きく変わるのはユーザー情報の表示部分です。ユーザー情報の表示部分はテーブルを使用しています。これまでですと、基本的にはタグ一つ一つを特定して値を取得するイメージでしたが、テーブルの場合、表形式での位置関係をイメージしての操作が可能です。
まずWebResponse#getTables()
というメソッドにより、テーブルタグのオブジェクトを取得します。フォームタグの時と同様に複数のオブジェクトが存在する場合がありますので、配列位置を指定する必要があります。この画面ではテーブルは一つしかないので、フォームの時と同様に0を指定します(3)。
取得したテーブルオブジェクトは縦軸と横軸を持ったString
の配列となっています。ここのでのテスト項目としては、動的なデータを表示する2列目のデータ部分について上から順に評価しています(4)。
LoginTest#testErrorTerminal()
最後に不正な端末からアクセスがあった場合のテストケースです。
/** * 不正な端末からのアクセス * * @throws MalformedURLException * @throws IOException * @throws SAXException */ public void testErrorTerminal() throws MalformedURLException, IOException, SAXException { // (1) // 端末 ID を設定 wc.setHeaderField("X-CZ-TID", "XXX"); // 初期画面表示 // ------------------------------------------------------------ WebRequest request = new GetMethodWebRequest( "http://localhost:8080/httpunitapp/login.jsp"); WebResponse response = wc.getResponse(request); // 入力フォーム // 今回は1つのみの入力フォームなので、配列位置は「0」 WebForm form = response.getForms()[0]; // 送信実行 form.submit(); // 遷移後の画面 // ------------------------------------------------------------ response = wc.getCurrentPage(); //System.out.println(response.getText()); // テスト実施 // 遷移画面 ID String sid = response.getHeaderField("X-CZ-SID"); assertEquals(sid, "SCZ001"); // メッセージコード HTMLElement elem = response.getElementWithID("msgCode"); String msgCode = elem.getText(); assertEquals(msgCode, "1"); // (2) // 他のケースに影響しないようクリアする wc.setHeaderField("X-CZ-TID", null); }
WebConversation#setHeaderField()
メソッドにて、ヘッダフィールド名を指定して値を設定します(1)。
リクエストヘッダなので、WebRequest#setHeaderField()
を使用すると考えるのが普通ですが、今までのコードにあるように、最初のリクエスト送信後、表示した画面を操作した上でWebForm#submit()
で送信処理が実行されてしまうため、事前に設定しておく必要があります(単に最初のリクエストを送信して終わるのであれば、WebRequest#setHeaderField()
で指定して問題ありません)。
それ以降は、入力値の部分など省力していますが、今までの流れと同様です。
テストメソッドの終了時には、メソッド冒頭で設定したヘッダ値をクリアします。これは、他のテストメソッドに影響しないようにするためです(2)。
まとめ
以上、HttpUnitを利用したブラウザユーザーインターフェイスでのテストの自動化について記述しました。
- xUnitを使用するように、ブラウザUIでも自動テストができます。
- サーバー側での実装の必要がありません(サーバー実装に依存しません)。
- 手操作では行えないHTTPヘッダの入力と評価ができます。
画面のテストは、最終的には実際に操作して、目視で確認する作業が必ず必要です。しかし、最終的に確認するに至るまでの作業については、本件のような手法を利用して省力化することが可能だと思います。Webシステムの画面開発、テストに利用してみてはいかがでしょうか。