テストケースの書き方 Tips集(2/2)
画面のJSP/HTMLソースでidを付与する
Seleniumを使用する際、操作する対象を特定する必要があります。Seleniumでは対象を特定するためのElementLocatorとしてDOMやxpathなどさまざまな方法が提供されていますが、id
属性で指定するのが一番簡単かつ確実です。従って、画面のJSPやHTMLソースを記述する際にあらかじめid
属性を付与することを推奨します。特に、以下の要素については画面のソース上でid
属性を付与することを推奨します。
画面の要素 | 使用するコマンド | 付与推奨の属性 |
table | verifyTable | id 属性 |
table要素については、IEを使用する場合はid
属性ではなく、name
属性でもverifyTable
コマンドを使用することができます。しかし、Firefoxを使用する場合は、name
属性だとエラーになってしまうので、id
属性を使用した方が良いでしょう。
コンボボックス(select要素)の検証
コンボボックスなどselect要素を指定するにはselect
コマンドを使いますが、select要素の検証にはassertSelected
コマンドやassertSelectOptions
コマンド、assertSelectedOptions
コマンドを使用します。
これらの違いは次のとおりです。
コマンド名 | 説明 |
assertSelectOptions | リストの一覧の検証 |
assertSelected | リストで何が選ばれているかの検証 |
assertSelectedOptions | リストで何が選ばれているかの検証(複数選択の場合) |
assertSelectedOptions
コマンドは、Seleniumバージョン0.7.0で追加されたコマンドです。コマンド書式や記述例は「Selenium 0.7 リファレンスガイド(日本語版)」を参照してください。
リンク先(href属性)の検証方法
Seleniumの仕様では、セキュリティ上の理由(クロスサイトスクリプティング対策)から外部サーバのURLを開くことができません。従って、外部へのリンク先に対する検証は、click
コマンドでURLを開いてassertTitle
するという手段が使えません。
そこで、assetAttribute
コマンドを使用してリンクのhref
属性に対する検証を実施することができます。例えば、書籍の情報を表示する画面で、Amazonへのリンクがあったとします。
<td rowspan="16" valign="top" class="book_detail_image"> <!--ここは書籍のISBNを元にアマゾンから画像を持ってくる--> <a href="http://www.amazon.co.jp/exec/obidos/ASIN/4774123412/" target="_blank"> <img src="http://images-jp.amazon.com/images/P/4774123412.09.MZZZZZZZ.jpg" border="0"></a> 画像をクリックするとAmazonのページが別ウィンドウで開きます。 </td> <td class="menu_book_detail"> 書籍ID: </td> <td class="content_book_detail"> 3 </td>
このリンク先に対するSeleniumのテストケースの書式は次のとおりです。
<tr> <td>assertAttribute</td> <td>xpath=//a@href</td> …【1】 <td>exact:http://www.amazon.co.jp/exec/obidos/ASIN/4774123412/</td> …【2】 </tr>
href
属性を指定。exact:
プリフィックスを付ける。 ポイントは、http://
の先頭にexact:
という文字列マッチングのprefixを付与することです。exact:
を付けないと、「cannot find PatternMatcher.strategies.http」というエラーが発生します。
xpath=//a[text()='リンク文字列']@href
なお、画面のソース上で、リンク先を相対パスで書いていた場合は注意が必要です。
<form name="BlankForm" method="post" action="/MyApp/generalLogin.do"> <input type="submit" name="submit" value="一般ユーザーログイン"> </form> <a href="026_guide.jsp">ご利用ガイド</a> …【1】
href
属性の記述が相対パスになっている。 href
属性を相対パスで指定した場合、assertAttribute
コマンドに対する動作がIEとFirefoxで異なります。
IEの場合
画面のソース上、href
属性の記述は026_guide.jspだけですが、リンク先として使用される属性にはホスト・ポート・コンテキストパスを含めた絶対パスになっています。例えば、"http://localhost:8080/MyApp/026_guide.jsp"です。つまり、テストケースの方でも絶対パスで記述する必要があります。ホスト(IPアドレス)も記述する必要があるため、テストを実施するサーバを変更した際にテストケースの記述も変更しなければならないので要注意です。なお、このような場合に、「実行するURL(IPアドレス)を変更できるようにする」で紹介した変数設定が有用です。
テストケースの記述は次のようになります。
<tr> <td>assertAttribute</td> <td>xpath=//a@href</td> <td>exact:http://localhost:8080/MyApp/026_guide.jsp</td> …【1】 </tr>
http://
で始まるのでexact:
プリフィクスも付ける。FireFoxの場合
Firefoxの場合は、assertAttribute
コマンドで取得できるhref
属性の内容は、画面のソース上に記述された通りになります。つまり上記の例で言うと"026_guide.jsp"だけとなります。
テストケースの記述は次のようになります。
<tr> <td>assertAttribute</td> <td>xpath=//a@href</td> <td>026_guide.jsp</td> …【1】 </tr>
後は、厳密ではなくなってしまうのですが、パターンマッチングを行う部分にワイルドカード(*)を使用するという方法もあります。この場合、IEでもFirefoxでもエラーを発生させずに動作させることが可能です。
<tr> <td>assertAttribute</td> <td>xpath=//a@href</td> <td>*026_guide.jsp</td> …【1】 </tr>
同じ表示のリンクが複数ある場合のクリック(指定)方法
例えば、同じタイトルの書籍で、書籍IDが異なっているような場合です。
この画面のHTMLソースは次のようになっています。
<td class="search_result_content"> <a href="/MyApp/dispBook.do?bookId=4">JUnitインアクション</a> </td> …(中略)… <td class="search_result_content"> <a href="/MyApp/dispBook.do?bookId=5">JUnitインアクション</a> …【1】 </td>
bookId
が異なる。表示は同じ。通常、リンクをクリックするには次のように、リンクとして表示されている文字列を指定をします。
<tr> <td>clickAndWait </td> <td>link=JUnitインアクション</td> <td></td> </tr>
上記の指定をした場合、Seleniumは一番最初にマッチしたものをクリックします。従って、上記の例では常に1番目(bookId=4)の書籍をクリックすることになってしまいます。このような場合、xpathを使用することによって、表示される文字列ではなくhref
属性を指定してクリックすることができます。
Seleniumのテストケースhtmlは次のようになります。
<tr> <td>clickAndWait </td> <td>xpath=//a[@href='http://localhost:8080/MyApp/dispBook.do?bookId=5']</td> <td></td> </tr>
href
属性のソース上の記述は相対パスですが、実際に使用される値はIEでは絶対パスなので上記のように記述が長くなってしまいます。そこで、xpathの文字列関数contains
を使用して特定の文字列を含んだhref
属性を指定することができます。href
属性に"bookId=5"を含むa要素を指定する場合は次のようになります。
<tr> <td>clickAndWait </td> <td>xpath=//a[contains(@href,'bookId=5')]</td> <td></td> </tr>
contains
を使用して記述することで以下のメリットがあります。
- テストケースに記述する量を少なくできる(それによってミスを少なくできる)。
- ブラウザによってリンクに対するパスの取得方法が違う(IE=絶対パス、Firefox=ソースの記述通り)が、その差を考慮する必要なしに両者で動作させることができる。
同じ表示が複数あることを検証するコマンド
Seleniumで表示された文字列を検証するコマンドがassertTextPresent
ですが、assertTextPresent
は同じ表示が複数あった場合、その表示がいくつあったのかは分かりません。そこで表示された文字列の回数を検証するコマンドを作成しました。このコマンドはSeleniumの開発コミュニティに寄贈されています。
assertTextPresentCount
指定したテキスト文字列の表示回数を検証します。
コマンド | ターゲット | バリュー |
assertTextPresentCount | 検証する文字列(表示される文字列) | 表示されている回数 |
verifyTextPresentCount | 検証する文字列(表示される文字列) | 表示されている回数 |
コマンド | ターゲット | バリュー |
verifyTextPresentCount | You are now logged in. | 1 |
assertTextPresentCount | error! | 2 |
assertTextPresentCount | You are now logged in. | 0 |
バリューには指定した文字列の表示回数を設定します。バリューが1であれば、assertTextPresent
と同様の動作、バリューが0であればassertTextNotPresent
と同様の動作ということになります。
このコマンドを使用するためには、「user-extensions.js」に以下のコードを追記します。
/* * assertTextPresentCount verify that the specified text is present * with specified counts in the page content. */ Selenium.prototype.assertTextPresentCount = function(expectedText, count) { var allText = this.page().bodyText(); var pattern = new RegExp(expectedText,"g"); LOG.debug("expect text =" + expectedText); LOG.debug("expect count=" + count); LOG.debug("matchingText=" + allText.match(pattern)); if(allText == "") { Assert.fail("Page text not found"); } else if(allText.indexOf(expectedText) == -1) { if (count != 0) { Assert.fail("'" + expectedText + "' count doesn't match."); } } else if(allText.match(pattern).length != count) { Assert.fail("'" + expectedText + "' count doesn't match."); } };
ボタン2度押しコマンド
セキュリティ対応の1つとして、[submit]ボタンの2度押し対策がよく問われます。このボタン2度押しを簡単に実行するコマンドを作成しました。
clickTwice
使用方法はclick
コマンドと同様です。このコマンドを使用するためには、「user-extensions.js」に以下のコードを追記します。
/* * Click Twice on the located element, and attach a callback to notify * when the page is reloaded. */ Selenium.prototype.doClickTwice = function(locator) { var element = this.page().findElement(locator); this.page().clickElement(element); this.page().clickElement(element); };
実は、このコマンドを使用しなくても、click
コマンド+clickAndWait
コマンドを続けて実行することでボタン2度押しを実現することができます。clickTwice
コマンドを使用した場合のメリットは、「ボタン2度押しである」ことが明示できることと、実施速度が10数msec速くなることです。
テストケースの書き直し
Seleniumの良い点は、回帰テストが容易に実行できることです。バグ発生時に、修正箇所だけでなく全項目をリグレッションとして容易に再試験することができます。ただし、テストケースの書き直しが発生する場合もあります。画面のJSP/HTMLソースを修正した場合と、アプリケーションの業務ロジックを修正した場合の、テストケースの修正要否は次のようになります。
画面の修正 | ロジックの修正 | テストケースの修正要否 |
修正なし | 修正なし | 修正不要 |
修正あり | 修正なし | 修正不要。assertTable で順番が変わる場合は修正必要。 |
修正なし | 修正あり | 修正必要。画面への出力内容が変わらない場合は修正不要。 |
修正あり | 修正あり | 修正必要 |
画面のレイアウト、例えばボタンの位置を変更したとしてもテストケースの修正は必要ありません。そのまま回帰テストを実行することができます。
ロジックを修正していなくても、assertTable
を使用しているときに修正が必要となることがあります。例えば、書籍の情報を表示している画面で著者名と出版社名の表示順序を変更する場合、著者名をassertTable
を用いて検証しているテストケースでは修正が必要となります。assetTable
ではなく、assertTextPresent
を使用して「著者名:○○○」という検証をしているテストケースでは修正が不要です。
画面のソースを修正しなくてもロジックを変更した場合は、基本的に修正が必要です。例えば、検索の条件を変更した場合、検索結果が変わることになるテストケースにおいて検索結果件数をassertTextPresent
検証している場合、テストケースの修正が必要です。
assetTextPresent
とassetTable
の使い分けの指針は次のとおりです。
- assertTextPresent
- assetTable