Top > MyPage
 

Seleniumのお試し(修正版)

2009-09-08 知久和郎 updated(というか、何年ぶりかに一新)

セレニウムとは

Javascriptを主に使って、ブラウザーベースのテストを行うフレームワークと言うところか。セレニウムホームページに詳しいので、詳細はこちらを参照してください。

セレニウムを使う時のメリットは次のようなものだろうか。

  1. テスト項目表を見ながら、手作業でテストをするところを、完全な自動でテストができる。
  2. ブラウザごとのテストが必要な場合が多いが、セレニウムはいろいろなブラウザーに対応しているので(ここを参照)、手間が相当省ける。
  3. JavaやPerlのスクリプトの中からもテストが可能のなので、テストファースト的にも利用できる。
  4. Excelとの連携なども別途考案されており、ドキュメント作成とテスト作成を同一に出来る。

もちろん、デメリットも存在する。

  1. 仕様変更等が起こった場合、それらのメンテナンスに相当手間取る。
  2. 人がテストを行う時には、時々無茶なことをやったりするが、その予想不可能なユーザーの無茶な挙動をセレニウムでは想定できないであろう(と思う。例えば、突然リロード---control-rを無意識に押下してしまうなど)。
  3. 例えば、Captchaなどで文字を画像にしてある文字列を入力しないと、投稿できるかどうかなどは(できないのは可能かもしれませんが)無理でしょう。

いずれにしろ、使い方によっては非常な強力なテストフレームワークだと思う。

まずは、素で使ってみる

Selenium Core

とりあえず、selenium-coreを使ってみよう。まずはSelenium Core June 10, 2009 1.0.1をダウンロードしてくる。ただ、テストの対象がないとしょうがないので、今回はTomcatのwarファイルをここに置いておくので、これをTomcatにデプロイするという形を取ります。つまり、次の手順でテストしてみよう。

  1. 上記リンクからダウンロード。展開したものをちょっとトップディレクトリーをseleniumにリネームしてtomcat_home/webapps/seleniumとしてコピーする。
  2. 上記warファイルをtomcat_home/webappsに置いて、Tomcatを立ち上げる。つまり、このアプリはhttp://localhost:8080/testSelenium/showFormというURLでフォームが現れるようになっているので、一応確認しておく。
  3. さて、Seleniumのテストは、htmlファイル内に書く。通常suiteファイルとテストファイルを作る。もちろん、スイートは1つ、テストファイルは必要に応じて1つ以上作成することになります。そのテストファイルは、例えば、次のようなものです。
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
          <title>TestShowForm</title>
        </head>
        <body>
          <table border='1'><tbody>
              <tr>
                <td rowspan='1' colspan='3' align='center' bgcolor='#ddddff'>入力画面</td>
              </tr>
              <tr>
                <td>open</td>
                <td>http://localhost:8080/testSelenium/showForm</td>
                <td></td>
              </tr>
              <tr><!-- タイトルが「seleniumのテスト」かどうか -->
                <td>verifyTitle</td>
                <td>seleniumのテスト</td>
                <td></td>
              </tr>
              <tr><!-- nameというフィールドに「ほげほげ」と入力 -->
                <td>type</td>
                <td>name</td>
                <td>ほげほげ</td>
              </tr>
              <tr><!-- passというフィールドに「puyopuyo」と入力 -->
                <td>type</td>
                <td>pass</td>
                <td>puyopuyo</td>
              </tr>
              <tr><!-- mailというフィールドに「hogehoge@gmail.com」と入力 -->
                <td>type</td>
                <td>mail</td>
                <td>hogehoge@gmail.com</td>
              </tr>
              <tr><!-- dojo.birthdayというフィールドに「1984-04-20」と入力 -->
                <td>type</td>
                <td>dojo.birthday</td>
                <td>1984-04-20</td>
              </tr>
              <tr><!-- sexというプルダウンの「男」を選択 -->
                <td>select</td>
                <td>sex</td>
                <td>男</td>
              </tr>
              <tr><!-- execute_0という実行をボタンをクリックし、ちょい待つ -->
                <td>clickAndWait</td>
                <td>execute_0</td>
                <td></td>
              </tr>
              <tr>
                <td rowspan='1' colspan='3' align='center' bgcolor='#ddddff'>確認画面</td>
              </tr>
              <tr><!-- ここで、確認画面に遷移するので、タイトルが「実行結果」かどうか -->
                <td>verifyTitle</td>
                <td>実行結果</td>
                <td></td>
              </tr>
              <tr><!-- nameというIDのテキストが「ほげほげ」かどうか -->
                <td>verifyText</td>
                <td>name</td>
                <td>ほげほげ</td>
              </tr>
              <tr><!-- passというIDのテキストが「puyopuyo」かどうか -->
                <td>verifyText</td>
                <td>pass</td>
                <td>puyopuyo</td>
              </tr>
              <tr><!-- mailというIDのテキストが「hogehoge@gmail.com」かどうか -->
                <td>verifyText</td>
                <td>mail</td>
                <td>hogehoge@gmail.com</td>
              </tr>
              <tr><!-- birthdayというIDのテキストが「1984/04/20」かどうか -->
                <td>verifyText</td>
                <td>birthday</td>
                <td>1984/04/20</td>
              </tr>
              <tr><!-- sexというIDのテキストが「男」かどうか -->
                <td>verifyText</td>
                <td>sex</td>
                <td>男</td>
              </tr>
          </tbody></table>
        </body>
    </html>

上記のコメント内に簡単に説明を入れたように、tdタグで3つ一組で入力していきます。英文法で言うところの、SVOOで、つまりSは全部Seleniumで書く必要がないので、「O(〜を)O(〜に)V(する)」で「O(〜に)」はVによって必要がない場合があるので、基本的にはこのVにあたるコマンドの使い方を覚えることが、当面必要だと思います。ちょっぴり説明を書きましたので、ここを参照にしてください。また、これは簡単な仕様をここで決めているので、ご覧ください。

上記のファイルとこれをTestShowForm.htmlとし、スイートは下記のような簡単なTestSeleniumSuite.htmlを作成し、そのファイルではなく、testRunner.htmlをブラウザーで開きます。即ち、今のコンテクストで言うならば、テストランナーとなります。

<html>
  <head><title>Test Suite for Selenium Test</title></head>
  <body>
    <table cellpadding="1" cellspacing="1" border="1">
      <tbody>
        <tr><td><b>Test Suite for Selenium Test</b></td></tr>
        <tr><td><a href="./TestCase1.html">showFormTest</a></td></tr>
      </tbody>
  </table>
  </body>
</html>

開いた画面は以下のよう。

test runner

それで、左上のテキストボックスに「../tests/TestSeleniumSuite.html」を入力して、Goをクリックすると、次のような画像が表示される。

test runner2

それで、右側の方にある緑色の三角をクリック(2つあるけど、今はテストが1つしかないので、どちらでも同じ。テストがたくさんある場合は、左だとそれら全てを行うし、右側のだと、1つだけになる(だと思う)。これで全て通るはずなんだけど、どうでしょうか?

Selenium-RC

Selenium Coreを利用する上で、ちょっと困るのは、最初にドキュメントルートへSeleinium Coreのファイルをコピーしなくてはならないと言うことが上げられます。もちろん、ローカルでテストするには問題ないわけですが、自分のWindowsでは動いているものが、本番サーバーの環境では動かない、ということは普通に起こりえることです。となると、本番サーバーでもテストしたい。しかしそのサーバーにはセキュリティやいたずらなどを想定すると、Seleinium Coreのファイルを送ることは無理だと言うことがあり得るというわけです。

また、下でも触れましたが、Seleniumのテーブルにテストケースを書く方法は、条件分岐などの細かい制御がしづらいところがあり、Javaなどのtestケースとしてテストした方がより柔軟にテストができる、というようなこともあり得ます。その場合、Selenium-RCを利用することになります。

そこで、Selenium Downloadへ行って、「Selenium RC June 10, 2009 1.0.1」をダウンロードしてきて、展開します。すると

  • selenium-java-client-driver-1.0.1
  • selenium-server-1.0.1
  • selenium-ruby-client-driver-1.0.1
  • selenium-python-client-driver-1.0.1
  • selenium-php-client-driver-1.0.1
  • selenium-perl-client-driver-1.0.1
  • selenium-dotnet-client-driver-1.0.1

というディレクトリーが出来ています。このなかで必要なのは「selenium-server-1.0.1」で、この中のファイル「selenium-server.jar」をどこでも良いのですが、上記で利用したテストスイートやテストケースファイルの近くに置きます。今回は、tomcat_home/seleniumに置いて(実際にはどこでもよいし、もともとこのディレクトリー自体なくてもOKなのですが、テストファイルがこのディレクトリのtestsにあるのでとりあえず)、次のようなコマンドを実行します。

java -jar selenium-server.jar -htmlSuite "*firefox" "http://localhost:8080/testSelenium/showForm" tests/TestSeleniumSuite.html tests/result.html

すると、次のような標準出力が出力され、

17:16:56.953 INFO - Java: Sun Microsystems Inc. 11.0-b15
17:16:56.953 INFO - OS: Windows XP 5.1 x86
17:16:56.953 INFO - v1.0.1 [2696], with Core v@VERSION@ [@REVISION@]
17:16:57.015 INFO - Version Jetty/5.1.x
17:16:57.015 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
17:16:57.015 INFO - Started HttpContext[/selenium-server,/selenium-server]
17:16:57.015 INFO - Started HttpContext[/,/]
17:16:57.015 INFO - Started SocketListener on 0.0.0.0:4444
17:16:57.015 INFO - Started org.mortbay.jetty.Server@1571886
17:16:57.093 WARN - It looks like your baseUrl (http://localhost:8080/testSelenium/showForm)
is pointing to a file, not a directory (it doesn't end with a /).
We're going to have to strip off the last part of the pathname.
17:16:57.156 INFO - Preparing Firefox profile...
17:17:02.390 INFO - Launching Firefox...
17:17:22.062 INFO - Checking Resource aliases
17:17:29.125 INFO - Checking Resource aliases
17:17:29.125 INFO - Received posted results
17:17:29.406 INFO - Killing Firefox...

tests/result.htmlとして、次のような画面のファイルが出力されています。

Selenium-RC result

というわけで、今回はたまたまローカルのTomcat上だったので、無理にSelenium-RCを使わずとも可能だったわけですが、この後、Junit上でテストを行ったり、別のサーバーにファイル等をコピーしないでテストが可能になるので、これを使わない手はないでしょう。

最後に、Selenium IDEというのがありますが、これはFirefoxのプラグインで、Firefoxでアクセスして、フィールドに値を入力したり、実行ボタンをクリックしたりすると、上記にあるようなテーブルのテストケースを自動で作成してくれるものです。テーブルの書き方やコマンドがわからないような場合はこれで作成して、書き方を勉強するのには便利だと思います。ただ、テストケースを書く人的コストが多いとテストを作成するのが結果的に面倒になり、やらなくなってしまうということも考えられ、可能なら、Selenium IDEなどは利用しなくても大丈夫になるようにしたいものだと、個人的には思います。

Excelを利用する方法、CodeZineでぃべろっぱーず・さいどThinkITなどや、ちょうど反対の発想のSeleniumのテストケースからエクセルに変換するSelenium Converter To Excelなど、ググればいくらでもあるので、この辺を利用するのも手でしょうし、perlなどを使って変換するもの(csv→テーブルのテストケース、csv→Junitのテストケースを作成するようなもの)を自作するという手もあるかもしれません。

コマンドの概要

seleniumのドキュメントを見れば、相当詳細に書いてありますので、これをこつこつ勉強すれことになるでしょうが、まずは、前提になっているいくつかの重要ポイントを列挙します。また一番最後に(まだ一覧だけでなんの説明もありませんが)Seleniumのアクション一覧SeleniumのAccessor(verifyやassertも同じ)一覧があるのでご参考ください。

  1. assert〜というコマンドとverify〜というコマンドは、基本的には、テストに失敗した時にテストが終了してしまうassert〜とテストに失敗してもそのままテストを続けるverify〜の違い。一通りテストを続けたい、と通常だと思うので、何でもverifyをするかもしれないが、ページのロードで失敗していたらその後のテストは意味がないので、時間の無駄です。なので、SeleniumのURLでは、最初のページのロードあたりはassert〜を使い、その後をverify〜にすると推奨しています。
  2. ページ内のテキストやボタンにアクセスする際の「locator」は例えば、
    <html>
     <body>
      <form id="loginForm">
       <input name="username" type="text" />
       <input name="password" type="password" />
       <input name="continue" type="submit" value="Login" />
       <input name="continue" type="button" value="Clear" />
      </form>
     </body>
    <html>
    
    とあった場合、これにアクセスするには次のようなパターンがあり得る。
    • Locating by Identifier
      1. identifier=loginForm (3行目)
      2. identifier=username (4行目)
      3. username (4行目)

      上記のフォームにアクセスする方法として、上記のように「idとname」属性があり、その両方に対して使えるのがこのidentifierで、デフォルトがもともと「identifier=〜」となっているので、この「identifier=〜」の最初の部分が必須ではなく、最後のように「continue」のような書き方が許されている。これは一見便利なんだけど、たまたまname属性とid属性が同じものが同ページ内にあるような時に失敗する可能性もあり得るので、多少の注意が必要でしょう。

    • Locating by Id
      1. id=loginForm (3行目)

      のように、id属性を直接指定するもので、これは省略が不可(「id=」部分)。

    • Locating by Name
      1. name=username (4行目)
      2. name=continue value=Clear (7行目)
      3. name=continue Clear (7行目)
      4. name=continue type=button (7行目)

      これはname属性を指定する場合だが、上記のように、value(省略可)やtype属性を指定することも可能。

    • Locating by XPath

      XPathは強力で、多少勉強しないと俄には分からないかもしれないが、それほど難しいものでもなく、以下のような指定をするので、あとはそこからの想像で書きながら少しずつ覚えるという手もあるかもしれない。

      1. xpath=/html/body/form[1] (3行目) - ルートからの絶対パス(これはhtmlの構造が変化するとちょっとずつ変わってしまう)
      2. //form[1] (3行目) - HTMLの最初のform
      3. xpath=//form[@id='loginForm'] (3行目) - idが「loginForm」form(この辺が無難か?)
      4. xpath=//form[input/\@name='username'] (4行目) - 最初のformで、inputの子エレメント(ここでは属性) nameが「username」のもの
      5. //input[@name='username'] (4行目) - 最初のinputエレメントのnameが「username」のもの
      6. //form[@id='loginForm']/input[1] (4)行目 - idが「loginForm」というformの最初の子エレメントであるinput
      7. //input[@name='continue'][@type='button'] (7行目) - nameが「continue」というinputでtypeが「button」のもの
      8. //form[@id='loginForm']/input[4] (7行目) - idが「loginForm」というformの4番目の子エレメントであるinput

      XPathは次のリンクで勉強できます。

    • Locating Hyperlinks by Link Text
      <html>
       <body>
        <p>Are you sure you want to do this?</p>
        <a href="continue.html">Continue</a>
        <a href="cancel.html">Cancel</a>
      </body>
      <html>
      

      のような場合

      1. link=Continue (4行目)
      2. link=Cancel (5行目)

      のようにaタグの要素を指定する。

    • Locating by DOM
       <html>
        <body>
         <form id="loginForm">
          <input name="username" type="text" />
          <input name="password" type="password" />
          <input name="continue" type="submit" value="Login" />
          <input name="continue" type="button" value="Clear" />
         </form>
       </body>
       <html>
      

      のような場合

      1. dom=document.getElementById('loginForm') (3行目)
      2. dom=document.forms['loginForm'] (3行目)
      3. dom=document.forms[0] (3行目)
      4. document.forms[0].username (4行目)
      5. document.forms[0].elements['username'] (4行目)
      6. document.forms[0].elements[0] (4行目)
      7. document.forms[0].elements[3] (7行目)

      DOMを勉強したいなら、W3Schoolsを参照のこと。

    • Locating by CSS
       <html>
        <body>
         <form id="loginForm">
          <input class="required" name="username" type="text" />
          <input class="required passfield" name="password" type="password" />
          <input name="continue" type="submit" value="Login" />
          <input name="continue" type="button" value="Clear" />
         </form>
       </body>
       <html>
      

      のような場合、CSSのselectorを利用して次のようにアクセすることも出来る(必要があるかどうかは別ですね)。

      1. css=form#loginForm (3行目)
      2. css=input[name="username"] (4行目)
      3. css=input.required[type="text"] (4行目)
      4. css=input.passfield (5行目)
      5. css=#loginForm input[type="button"] (4行目)
      6. css=#loginForm input:nth-child(2) (5行目)

また、verifyTextPresent、verifyTitle、verifyAlert、assertConfirmation、verifyText、verifyPromptのようなコマンドにはテキストとのマッチングが判断基準になりますが、そのマッチングには次のような場合があります。

  1. Globbing Patterns

    通常のDOSやLinuxなので使われる「*」が利用でき、また次のような文字クラスも利用できます。

    • [aiueo] はaiueoのいずれか。
    • [0-9] は数字
    • [a-zA-Z0-9] はアルファベット大文字、小文字

    実際の例としては次のよう。

    click link=glob:Film*Television Department           
    verifyTitle glob:*Film*Television*           

    上記の例は、「glob:」が付いていますが、これはデフォルトなので省略が可能。それで上記の例を言葉にすれば、「Film云々Television Department」というリンクをクリックし(「云々」は空文字でもOK。以下同様)、開いたページのタイトルが「云々Film云々Television云々」であるかどうかをテストしていることになります。

  2. 正規表現

    正規表現は簡単に説明できないので、ここでは説明しません。具体的な例として

    open http://weather.yahoo.com/forecast/USAK0012.html           
    verifyTextPresent egexp:Sunrise: *[0-9]{1,2}:[0-9]{2} [ap]m           

    上記の例は「http://weather.yahoo.com/forecast/USAK0012.html」を開くと、「Sunrize:」に続き、半角スペースが0個以上続き、数字が1以上2以下で次が「:」、続いて数字が2個続き、半角スペース、最後が「amかpm」になっている文字列があるかどうかをテストしていることになります。

  3. Exact Patterns
    select //select glob:Real *
    select //select exact:Real *
    select //select regexp:Real \*

    上記の1つめは、globがあるのでRealの次に何かあるか、或いは何かがあっても(例えば「Real Numbers」)選択されるが、2番目の3番目のものはまさに「Real *」という文字列しか選択されない。3つめのは単に「*」をエスケープしているもの。

次に「The “AndWait” Commands」というものが、一部のコマンド(例えば、「clickAndWait」)には存在します。すると、Seleniumはページがロードされるまで待つので、なかなかロードされないよう場合は、タイムアウトを起こす可能性があるようです。

また、Ajaxのようにページがリフレッシュしないようなものにはこの「AndWait」は使えず、waitForElementPresentやwaitForVisibleのような「waitFor」コマンドを利用することになります。

また、この方法によるテストの流れは、完全に単なる上から下へと順番に行われるのであって、ifなどの条件で分岐するようなことは行えない。なのでそのようなことが必要な場合は次の3つのオプションを利用すると良いでしょう。

  1. Selenium-RCを使って走らせ、JavaやPHPのようなクライアントのライブラリーをフローのコントロールをする場面で利用するという方法。
  2. 小さなJavascriptをstoreEvalコマンドを使って、Seleniumのスクリプト内で走らせると言う方法。
  3. the goto_sel_ide.jsをインストールし、拡張する方法。

さらに、「Store Commands and Selenium Variables」つまり「コマンドやSeleniumの変数の保存」という考え方があり、これにより、スクリプトの最初に定数を保存したりすることが出来る。具体的に述べよう。

storeコマンドは単純にSeleniumの変数にデータを保存するものです。2つの引数を保ち、最初のが保存する内容で、2つめのは保存する変数名です。

store paul@mysite.org userName

のようにすると、userNameという変数にpaul@mysite.orgが保存され、次のような形で参照できます。

verifyText //div/p ${userName}

つまり、上記の例では、divのpタグ内が「paul@mysite.org」であるというテストになるわけです。あるいは

type id=login ${userName}

だったら、idがloginというところに「paul@mysite.org」を入力すると言うことになります。また、このstoreコマンド以外に

  • storeElementPresent

    verifyElementPresentに対応するもので、単に boolean値--”true”か“false”(エレメントがあるかどうか)を保存するもの。

  • storeText

    verifyTextに対するもので、locatorを使い、そこにテキストがあったら、それを保存する。

  • storeEval

    このコマンドは最初の引数としてスクリプトを与える。StoreEvalはその変数内に埋め込まれたスクリプトを走らせその結果をテストできるようにする。

  • JavaScript and Selenese Parameters

    JavaScriptでは、スクリプトとnon-スクリプト(たいていは式)という2つのタイプが使われる。ほとんどの場合、Seleniumのパラメータとして使われるJavaScriptの断片の中にある変数にアクセスしたり、操作したいと考えるであろう。テストケース内で作成された全ての変数は連想配列に保存される。そしてその連想配列はstoredVarsという名前です。つまり、storedVars[‘yourVariableName’]でアクセスしたり、操作したり出来ます。

  • JavaScript Usage with Script Parameters

    assertEval、 verifyEval、 storeEval、 あるいはwaitForEvalというようないくつかのコマンドはスクリプトの引数を指定します。これらの引数は特別なシンタックスは必要ありません。Selenium-IDEユーザーは単にJavaScriptの断片を妥当なフィールド(普通は、ターゲットフィールド)に入力するだけです(というのもスクリプトの引数はたいていは最初、或いは1つの引数しかない場合だから)。次の例は、単純な数字の計算を行うのに使われるJavaScriptの断片をどのように使われるかという例です。

    store 10 hits
    storeXpathCount //blockquote blockquotes
    storeEval storedVars[‘hits’]-storedVars[‘blockquotes’] paragraphs

    hitsに10を保存し、blockquoteの数をblockquotesに保存し、最後に、hitsからblockquotesを引き算し、それをparagraphsに保存する、というような意味となります。次の例では

    store Edith Wharton name
    storeEval storedVars[‘name’].toUpperCase() uc
    storeEval storedVars[‘name’].toLowerCase() lc

    nameに「Edith Wharton」を保存し、それを大文字にしたものをucに保存、小文字にしたものをlcに保存する、という意味になります。

  • JavaScript Usage with Non-Script Parameters

    Non-スクリプトの引数は

    store league of nations searchString
    type q javascript{storedVars[‘searchString’].toUpperCase()}

    「league of nations」をsearchStringに保存し、それを「q」というidかnameのフィールドに大文字に変更して入力する、という意味になります。

  • echo - The Selenese Print Command

    テストのoutputにテキストを出力することが可能です。これは、テストの進行状況などの情報として使えば、有用でしょう。或いは、テストに失敗した時の失敗箇所を探すのにも有用です。

    echo Testing page footer now.           
    echo? Username is ${userName}           
  • Alerts, Popups, and Multiple Windows

    これは、

    assertEval confirm('続けますか?') TRUE

    などとJavascriptを使って、ポップアップを上げることを言っているのかどうかはわかりません(というのもSeleniumのホームページにも、「This section is not yet developed.」とあるので。

とりあえず、これからやることの指針

以前、一度試しにSeleniumを使った時のメモを更新しました。struts2にて、テストのテストを行うのですが、そこにたどり着く部分が長いですが、ご勘弁を。

大雑把に言うと次のようになります。

  1. フォームの表示する。
  2. フォームにデータを入力、そこで値検証をする。
    • 名前---必須
    • パスワード---必須
    • メールアドレス---必須とメールアドレスとしての整合性
    • 誕生日---必須と日付であることの整合性
    • 性別---1か2
  3. 値検証にNGの場合は同じ入力画面を表示する。
  4. 値検証にOKの場合は確認画面を表示する。

環境設定

mavenで管理して、mavenでテストをする、という方向でのselenium調査なので、まずはmavenから。

maven

mavenは最新じゃありませんが、現状はapache-maven-2.0.10なのですが、たぶん、最新のMaven 2.2.1の場合は、そう置き換えてください。

SET Path ..;C:\maven-2.0.10\bin;...
set MAVEN_HOME=C:\maven-2.0.10

mavenでプロジェクトを作成

環境変数を活かすために、一度コンピュータをリブート。次にコマンドラインから(僕の場合はbashのコンソールから)

cd workspace
bash
$ mvn archetype:generate -DgroupId=Und  -DartifactId=testSelenium -Dversion=0.0.1

で、どんなものを作るか聞かれますが、ここでは18番を選ぶと、次のようなファイル群が作成できます。

testSelenium
├ src
│ └ main
│    ├ resources
│    └ webapp
│       ├ WEB-INF
│       │ └ web.xml
│       └ index.jsp
└ pom.xml

というひな形です。色々ダウンロードをしていますが、これはローカルな環境にセンターリポジトリーから必要なライブラリーをダウンロードしていて、自動で行われます。とりあえず無視しましょう。

Eclipseのプロジェクトにするために、先ほどのbash上で

cd testSelenium
mvn eclipse:eclipse

を実行し、eclipse上からimportします。

pom.xml

できたpom.xmlでは役に立たないので、次の方針に従って、書き換えます。

  1. integration-testというphaseでテストを行う(これは後述するように、mvn packageでは実行されない)。
  2. integration-testを行う前に、testSeleniumというアプリをTomcatから削除し、tomcatを起動する。
  3. selenium-serverをテスト前に立ち上げる。
  4. テスト後、tomcatを終了させる。

上記の方針でできたpom.xmlは以下のようです(相当悪戦苦闘したので、無駄なのも混入していそうです)。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Und</groupId>
  <artifactId>testSelenium</artifactId>
  <packaging>war</packaging>
  <version>0.0.1</version>
  <name>testSelenium Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>testSelenium</finalName>
  </build>
</project>
 

完全にこれは、素のものなので、これをとりあえずstruts2用のものにしてみよう(今回はstruts2でテストしてみます)。次のようなものにします(若干無駄なものもあるかもしれません)。また、途中にあるは修正しなくてはならないところです。

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Und</groupId>
  <artifactId>testSelenium</artifactId>
  <packaging>war</packaging>
  <version>0.0.1</version>
  <name>testSelenium Maven Webapp</name>
  <url>http://www.chikkun.com</url>
  <repositories>
    <repository>
      <id>openqa</id>
      <name>OpenQA Repository</name>
      <url>http://nexus.openqa.org/content/repositories/releases/</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>codehaus snapshot repository</id>
      <url>http://snapshots.repository.codehaus.org/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </pluginRepository>
  </pluginRepositories>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-core</artifactId>
      <version>2.1.6</version>
    </dependency>
    <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-dojo-plugin</artifactId>
      <version>2.1.6</version>
    </dependency>
    <dependency>
      <groupId>com.opensymphony</groupId>
      <artifactId>xwork</artifactId>
      <version>2.1.2</version>
    </dependency>
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib-nodep</artifactId>
      <version>2.2</version>
    </dependency>
    <dependency>
      <groupId>commons-digester</groupId>
      <artifactId>commons-digester</artifactId>
      <version>2.0</version>
    </dependency>
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.8.0</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.15</version>
    </dependency>
    <dependency>
      <groupId>org.openqa.selenium.server</groupId>
      <artifactId>selenium-server</artifactId>
      <version>1.0-20081010.060147</version>
    </dependency>
    <dependency>
      <groupId>org.openqa.selenium.client-drivers</groupId>
      <artifactId>selenium-java-client-driver</artifactId>
      <version>0.9.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.4</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>testSelenium</finalName>
    <outputDirectory>${basedir}/target/testSelenium/WEB-INF/classes</outputDirectory>
    <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
    <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
    <testOutputDirectory>${basedir}/target/test-classes</testOutputDirectory>
    <resources>
      <resource>
        <directory>${basedir}/src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.ftl</include>
          <include>**/*.properties</include>
        </includes>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${basedir}/src/test/java</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.ftl</include>
          <include>**/*.properties</include>
        </includes>
      </testResource>
    </testResources>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>selenium-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>start</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>start-server</goal>
            </goals>
            <configuration>
              <background>true</background>
              <logOutput>true</logOutput>
              <multiWindow>true</multiWindow>
            </configuration>
          </execution>
          <execution>
            <id>stop</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>stop-server</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
            <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <dependencies>
          <dependency>
            <groupId>sun.jdk</groupId>
            <artifactId>tools</artifactId>
            <version>1.7.0</version>
            <scope>system</scope>
            <systemPath>${env.JAVA_HOME}/lib/tools.jar</systemPath>
          </dependency>
        </dependencies>
        <executions>
          <execution>
            <id>startcatalina</id>
            <phase>pre-integration-test</phase>
            <configuration>
              <tasks>
                <exec dir="${basedir}" executable="pre.bat" os="Windows XP" spawn="yes"/>
              </tasks>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.codehaus.cargo</groupId>
        <artifactId>cargo-maven2-plugin</artifactId>
        <version>1.0.1-SNAPSHOT</version>
        <configuration>
          <wait>true</wait>
          <container>
            <containerId>tomcat6x</containerId>
            <type>remote</type>
          </container>
          <configuration>
            <type>runtime</type>
            <home>${catalina.home}</home>
            <properties>
              <cargo.tomcat.manager.url>http://localhost:8080/manager</cargo.tomcat.manager.url>
              <cargo.remote.username>chikkun</cargo.remote.username><!-- ★ -->
              <cargo.remote.password>kazukun</cargo.remote.password><!-- ★ -->
            </properties>
          </configuration>
          <deployer>
            <type>remote</type>
            <deployables>
              <deployable>
                <groupId>${groupId}</groupId>
                <artifactId>${artifactId}</artifactId>
                <type>war</type>
              </deployable>
            </deployables>
          </deployer>
        </configuration>
        <executions>
          <execution>
            <id>post-container</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>deployer-deploy</goal>
            </goals>
          </execution>
<!--          <execution>
            <id>start-container</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>deployer-undeploy</goal>
            </goals>
          </execution>
          <execution>
            <id>clean-undeploy</id>
            <phase>pre-clean</phase>
            <goals>
              <goal>deployer-undeploy</goal>
              <goal>stop</goal>
            </goals>
          </execution>-->
        </executions>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>selenium-maven-plugin</artifactId>
        <configuration>
          <browser>*firefox</browser>
          <suite>src/test/java/com/chikkun/selenium/TestSeleniumSuite.html</suite>
          <startURL>http://localhost:8080/testSelenium/showForm</startURL>
        </configuration>
        <executions>
          <execution>
            <id>test</id>
            <phase>test</phase>
            <goals>
              <goal>selenese</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <dependencies>
          <dependency>
            <groupId>sun.jdk</groupId>
            <artifactId>tools</artifactId>
            <version>1.7.0</version>
            <systemPath>${env.JAVA_HOME}/lib/tools.jar</systemPath>
          </dependency>
        </dependencies>
        <executions>
          <execution>
            <id>stopcatalina</id>
            <phase>post-integration-test</phase>
            <configuration>
              <tasks>
                <echo message="here you are"/>
                <exec dir="${basedir}" executable="post.bat" os="Windows XP" spawn="yes"/>
              </tasks>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>**/selenium/*Test.java</exclude>
          </excludes>
        </configuration>
        <executions>
          <execution>
            <id>integration-tests</id>
            <phase>integration-test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <excludes>
                <exclude>none</exclude>
              </excludes>
              <includes>
                <include>**/selenium/*Test.java</include>
              </includes>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

mvn eclipse:eclipseを再度やって必要なjarファイルをダウンロードし、クラスパスも更新してみます。そうそうその前に忘れちゃならないのは、eclipseのworkspace/testSelenium/src/main/javaとworkspace/testSelenium/src/test/javaをディレクトリーとして作成しておかないと。

また、上記のpom.xmlで実行しているバッチが2つあります。本来はmavenだけで何とかしたかったのですが、一度テストをした後にundeployしても、いくつかのjarファイルがtomcatがロードしてしまっているので、削除されず、testSeleniumというディレクトリーが残ってしまい、再度テストを行っても今度はそのディレクトリがあるせいでdeployできない、という現象に悩まされ、解決できませんでした。なので、やむを得ず、テストを行う前に、そのバッチの中でディレクトリーなどを削除してしまい、Tomcatを起動し、そしてテストを行い、最後にTomcatを停止してしまうバッチを走らせています。それぞれ2つのバッチは、pre.batpost.batです。内容は以下のよう。pre.batが

@echo off
cd %CATALINA_HOME%\bin
if exist ..\webapps\testSelenium rmdir /s /q ..\webapps\testSelenium
if exist ..\webapps\testSelenium.war rm /q ..\webapps\testSelenium.war
cmd /c startup.bat
cd %~dp0

と、post.batが

@echo off
cd %CATALINA_HOME%\bin
call shutdown.bat
cd %~dp0

です。ここで注意したいのはCATALINA_HOMEという環境変数、私の環境ではC:/Tomcat 6.0をセットしておかなくてはなりません。こうしておけば、別の人が別のディレクトリーにTomcatをインストールしていてもOKでしょう。

最後にテスト、テストと言っていますが、今回のテストはintegration-testのことで、単体テストではありません。単体テストはmvn packaggeでwarファイルを作成する時も実行されます。が、今回のintegration-testは実行されません。ただはまったのはmvn integration-testとすると、何故か、上記のpom.xml内のpost-integration-testが実行されず、それがなぜだかわからず相当無駄な時間を費やしてしまいました。実際にはそれでもintegration-test自体は行われるのですが、その後のpost-integartion-test(今回はpost.batを実行)を実行したいのであれば、mvn installを実行します。

もともと、mavenは次のようなphaseがあり、integration-testというphaseで終わると、その後のpost-integration-testは実行されないらしい(やれやれ)。

validate プロジェクトに必要な情報が揃っているか検証する。
generate-sources ソースコードを生成する。
process-sources ソースコードに対してフィルタにかけるなどの処理を行う。
generate-resources package フェイズで生成するパッケージに含めるためのリソースを生成する。
process-resources パッケージングの準備として、(必要な処理があればそれを行いながら) リソースを配布用ディレクトリにコピーする。
compile プロジェクトのソースコードをコンパイルする。
process-classes コンパイルにより生成されたファイルに対する処理を行う (生成されたクラスファイルに対してバイトコード・レベルの操作など)。
generate-test-sources テスト用のソースコードを生成する。
process-test-sources テスト用のソースコードに対してフィルタをかけるなどの処理を行う。
generate-test-resources テスト用のリソースを生成する。
process-test-resources テスト用のリソースを (必要な処理があればそれを行いながら) 配布用ディレクトリにコピーする。
test-compile テスト用のソースコードをコンパイルする。
test テストを実行する。
package コンパイルしたコードやリソースを配布用のフォーマット (JAR や WAR, EAR など) でパッケージングする。
pre-package-integration-test 統合テストを行うために必要な、環境のセットアップなどの処理を行う。
integration-test 必要に応じて統合テストを実行できる環境へパッケージの配備・処理を行う。
post-integration-test 統合テスト後に必要なクリーンアップ処理を行う。
verify パッケージが品質基準を満足しているか検証する。
install パッケージをローカルリポジトリにインストールする。 これによりローカルにある他のプロジェクトから参照することができるようになる。
deploy パッケージをリモートリポジトリにコピーする。 これにより他の開発者やプロジェクトから参照することができるようになる。

web.xmlの修正

さてさて、このあとはテストの対象となるアプリの作成ですが、一番最初の頃に述べたように、Tomcatのwarファイルをここに置いておいたので、特に対象のアプリの内容には興味のない人はダウンロードして、実際のテストをさくせいするここへ飛んでください。んで、一応簡単にその中身を説明すると、まずは最初にmavenで作成したweb.xmlは以下のようでした。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>
                                                

これを、struts2が動くように次のように変更する。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 <display-name>Test for Selenium</display-name>

 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
 </welcome-file-list>
</web-app>
                                                

というように変える。

それで、表示のためのクラスと、resultとしてのテンプレート(Freemarker)、そして、struts.xmlを作成する。

  1. Classは次のようなcom.chikkun.selenium.ShowForm.javaを作成。
    package com.chikkun.selenium;
    import java.util.Calendar;
    import com.opensymphony.xwork2.ActionSupport;
    /**
     * @author chikkun
     */
    public class ShowForm extends ActionSupport{
        private static final long serialVersionUID = 1965663002559015165L;
        private String name;
        private String mail;
        private Integer sex;
        private String pass;
        private Calendar birthday;
        
        public String showForm() throws Exception {
            return "success";
        }
        public String execute() throws Exception {
            return "success";
        }
        public String getName() {
            return this.name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getMail() {
            return this.mail;
        }
        public void setMail(String mail) {
            this.mail = mail;
        }
        public Integer getSex() {
            return this.sex;
        }
        public void setSex(Integer sex) {
            this.sex = sex;
        }
        public String getPass() {
            return this.pass;
        }
        public void setPass(String pass) {
            this.pass = pass;
        }
        public Calendar getBirthday() {
            return this.birthday;
        }
        public void setBirthday(Calendar birthday) {
            this.birthday = birthday;
        }
    
    }
                                                            
    
  2. 次に、フォームと確認画面のテンプレート2つ(form.ftlとconfirm.ftl)。
    • templates/form.ftl
      <html>
      <head>
          <title>seleniumのテスト</title>
          </style>
          <@s.head/>
          <@sx.head/>
          <meta content="-1" http-equiv="Expires"/>
          <meta content="no-cache" http-equiv="Pragma"/>
          <meta content="no-cache" http-equiv="Cache-Control"/>
      </head>
      
      <body class="composite">
      <div align="center" style="width:800px;">
      <@s.form action="execute" method="post" validate="true" theme="xhtml" enctype="multipart/form-data">
          <@s.textfield label="名前" name="name"/>
          <@s.textfield label="パスワード" name="pass"/>
          <@s.textfield label="メールアドレス" name="mail"/>
          <@sx.datetimepicker label="誕生日" name="birthday" displayFormat="yyyy-MM-dd" value="%{'today'}"/>
          <@s.select label="性別" list=r'#{"1":"男","2":"女"}' value="#{2}" name="sex" />
          <@s.submit value="実行"/>
          <@s.reset value="リセット"/>
      </@s.form>
      </div>
      </body>
      </html>
      
    • templates/confirm.ftl
      <html>
      <head>
      <title>実行結果</title>
      </head>
      <body>
      <h1>実行結果表示</h1>
          <table>
              <@s.label label="お名前" name="name"/>
              <@s.label label="メールアドレス" name="mail"/>
              <@s.label label="パスワード" name="pass"/>
              <tr>
                  <td>性別:</td>
                  <td id="sex">
                  <#if sex == 1>
                      男
                      <#else>
                      女
                  </#if>
                  </td>
              </tr>
              <tr>
                  <td>誕生日:</td>
                  <td id="birthday"><@s.date label="誕生日" name="birthday" format="yyyy/MM/dd"/></td>
              </tr>
          </table>
      </body>
      </html>
      
  3. src/main/java/struts.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    
    <struts>
    
        <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
        <constant name="struts.devMode" value="false"/>
        <constant name="struts.custom.i18n.resources" value="MessageResources"/>
        <constant name="struts.i18n.encoding" value="Windows-31J"/>
    
        <package name="testSelenium" namespace="/" extends="struts-default" abstract="false">
            <action name="showForm" class="com.chikkun.selenium.ShowForm" method="showForm">
                <result name="success" type="freemarker">/templates/form.ftl</result>
            </action>
            <action name="execute" class="com.chikkun.selenium.ShowForm" method="execute">
                <result name="success" type="freemarker">/templates/confirm.ftl</result>
                <result name="input" type="freemarker">/templates/form.ftl</result>
            </action>
        </package>
    </struts>
    
  4. src/main/java/com/chikkun/selenium/ShowForm-execute-validation.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
     "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    
    <validators>
        <field name="name">
            <field-validator type="requiredstring">
                <message>名前は必須です。</message>
            </field-validator>
        </field>
    
        <field name="mail">
            <field-validator type="requiredstring">
                <message>メールアドレスは必須です。</message>
            </field-validator>
            <field-validator type="email">
                <message>メールアドレスの形式にしてください。</message>
            </field-validator>
        </field>
    
        <field name="pass">
            <field-validator type="requiredstring">
                <message>パスワードは必須です。</message>
            </field-validator>
        </field>
    
        <field name="birthday">
            <field-validator type="required">
                <message>誕生日は必須です。</message>
            </field-validator>
            <field-validator type="date">
                <message>誕生日は日付の形式で入力してください。</message>
            </field-validator>
        </field>
    
        <field name="sex">
            <field-validator type="required">
                <message>性別は必須です。</message>
            </field-validator>
            <field-validator type="int">
                <param name="min">1</param>
                <param name="max">2</param>
                <message>性別は「男/女」のいずれかをお選びください。</message>
            </field-validator>
        </field>
    </validators>
    

これでmvn packageしてできたtarget/testSelenium.warをtomcat君にdeployして、フォーム画面が表示されるとやっとこさ準備完了。

ようやくテスト作成

package com.chikkun.selenium;

import junit.framework.TestCase;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.SeleniumException;

public class SeleniumTest  extends TestCase {
    private DefaultSelenium selenium;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        selenium = createSeleniumClient("http://localhost:8080/testSelenium");
        selenium.start();
    }

    @Override
    public void tearDown() throws Exception {
        selenium.stop();
        super.tearDown();
    }

    protected DefaultSelenium createSeleniumClient(String url) throws Exception {
        return new DefaultSelenium("localhost", 4444, "*firefox", url);
    }

    public void testHelloWorld() throws Exception {
        try {
            selenium.open("http://localhost:8080/testSelenium/showForm");
            assertEquals("seleniumのテスト", selenium.getTitle());
            selenium.type("name", "ほげほげ");
            selenium.type("pass", "puyopuyo");
            selenium.type("mail", "hogehoge@gmail.com");
            selenium.select("sex", "男");
            selenium.type("dojo.birthday", "1984-04-20");
            selenium.click("execute_0");
            selenium.waitForPageToLoad("30000");
            //ページが遷移
            assertEquals("実行結果", selenium.getTitle());
            assertEquals("ほげほげ", selenium.getText("id=name"));
            assertEquals("puyopuyo", selenium.getText("id=pass"));
            assertEquals("男", selenium.getText("id=sex"));
            assertEquals("1984/04/20", selenium.getText("id=birthday"));
            
        } catch (SeleniumException ex) {
            fail(ex.getMessage());
            throw ex;
        }
    }

}

と記述し、コマンドラインから、同様に

 mvn install 

すると、標準出力を引用すると(最初の頃のwarファイルを作成している当たりは省略して)

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.chikkun.selenium.SeleniumTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 23.968 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] [selenium:stop-server {execution: stop}]
Stopping Selenium server...
Stop request sent
[INFO] [antrun:run {execution: stopcatalina}]
[INFO] Executing tasks
     [echo] here you are
[INFO] Executed tasks
[INFO] [install:install]
[INFO] Installing C:\cygwin\home\chikkun\workspace\testSelenium\target\testSelen
ium.war to C:\Documents and Settings\chikkun\.m2\repository\Und\testSelenium\0.0
.1\testSelenium-0.0.1.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 52 seconds
[INFO] Finished at: Tue Sep 08 09:52:31 JST 2009
[INFO] Final Memory: 21M/38M
[INFO] ------------------------------------------------------------------------

と成功した旨が報告される。やったあ!

[2007-02-19 11:22], modified on [2009-09-08]

Selenium Appendix

Selenium Actions

おいおい、備考を充実させていきます\(^o^)/。

コマンド 引数1 引数2 備考
addLocationStrategy strategyName functionDefinition  
addScript scriptContent scriptTagId  
addSelection locator optionLocator  
allowNativeXpath allow    
altKeyDown      
altKeyUp      
answerOnNextPrompt answer    
assignId locator identifier  
break      
captureEntirePageScreenshot filename kwargs  
check locator    
chooseCancelOnNextConfirmation      
chooseOkOnNextConfirmation      
click locator    
clickAt locator coordString  
close      
contextMenu locator    
contextMenuAt locator coordString  
controlKeyDown      
controlKeyUp      
createCookie nameValuePair optionsString  
deleteAllVisibleCookies      
deleteCookie name optionsString  
deselectPopUp      
doubleClick locator    
doubleClickAt locator coordString  
dragAndDrop locator movementsString  
dragAndDropToObject locatorOfObjectToBeDragged locatorOfDragDestinationObject  
dragdrop locator movementsString  
echo message    
fireEvent locator eventName  
focus locator    
goBack      
highlight locator    
ignoreAttributesWithoutValue ignore    
keyDown locator keySequence  
keyPress locator keySequence  
keyUp locator keySequence  
metaKeyDown      
metaKeyUp      
mouseDown      
mouseDownAt locator coordString  
mouseDownRight locator    
mouseDownRightAt locator,coordString    
mouseMove locator    
mouseMoveAt locator coordString  
mouseOut locator    
mouseOver locator    
mouseUp locator    
mouseUpAt locator coordString  
mouseUpRight locator    
mouseUpRightAt locator coordString  
open url    
openWindow url windowID  
pause waitTime    
refresh      
removeAllSelections locator    
removeScript scriptTagId    
removeSelection locator optionLocator  
rollup rollupName kwargs  
runScript script    
select selectLocator optionLocator  
selectFrame locator    
selectPopUp windowID    
selectWindow windowID    
setBrowserLogLevel logLevel    
setCursorPosition locator position  
setMouseSpeed pixels    
setSpeed value    
setTimeout timeout    
shiftKeyDown      
shiftKeyUp      
store expression variableName  
submit formLocator    
type locator value  
typeKeys locator value  
uncheck locator    
useXpathLibrary libraryName    
waitForCondition script timeout  
waitForFrameToLoad frameAddress timeout  
waitForPageToLoad timeout    
waitForPopUp windowID timeout  
windowFocus      
windowMaximize      

Selenium Accessors

アクセッサーはそれに伴いassertverifyが自動的に作成されている。

コマンド 引数1 引数2 関連 備考
assertErrorOnNext message   * assertNotErrorOnNext ( message )
* verifyErrorOnNext ( message )
* verifyNotErrorOnNext ( message )
* waitForErrorOnNext ( message )
* waitForNotErrorOnNext ( message )
 
assertFailureOnNext message   * assertNotFailureOnNext ( message )
* verifyFailureOnNext ( message )
* verifyNotFailureOnNext ( message )
* waitForFailureOnNext ( message )
* waitForNotFailureOnNext ( message )
 
assertSelected selectLocator optionLocator * assertNotSelected ( selectLocator, optionLocator )
* verifySelected ( selectLocator, optionLocator )
* verifyNotSelected ( selectLocator, optionLocator )
* waitForSelected ( selectLocator, optionLocator )
* waitForNotSelected ( selectLocator, optionLocator )
 
storeAlert variableName   * assertAlert ( pattern  )
* assertNotAlert ( pattern )
* verifyAlert ( pattern )
* verifyNotAlert ( pattern )
* waitForAlert ( pattern )
* waitForNotAlert ( pattern )
 
storeAllButtons variableName   * assertAllButtons ( pattern  )
* assertNotAllButtons ( pattern )
* verifyAllButtons ( pattern )
* verifyNotAllButtons ( pattern )
* waitForAllButtons ( pattern )
* waitForNotAllButtons ( pattern )
 
storeAllFields variableName   * assertAllFields ( pattern  )
* assertNotAllFields ( pattern )
* verifyAllFields ( pattern )
* verifyNotAllFields ( pattern )
* waitForAllFields ( pattern )
* waitForNotAllFields ( pattern )
 
storeAllLinks variableName   * assertAllLinks ( pattern  )
* assertNotAllLinks ( pattern )
* verifyAllLinks ( pattern )
* verifyNotAllLinks ( pattern )
* waitForAllLinks ( pattern )
* waitForNotAllLinks ( pattern )
 
storeAllWindowIds variableName   * assertAllWindowIds ( pattern  )
* assertNotAllWindowIds ( pattern )
* verifyAllWindowIds ( pattern )
* verifyNotAllWindowIds ( pattern )
* waitForAllWindowIds ( pattern )
* waitForNotAllWindowIds ( pattern )
 
storeAllWindowNames variableName   * assertAllWindowNames ( pattern  )
* assertNotAllWindowNames ( pattern )
* verifyAllWindowNames ( pattern )
* verifyNotAllWindowNames ( pattern )
* waitForAllWindowNames ( pattern )
* waitForNotAllWindowNames ( pattern )
 
storeAllWindowTitles variableName   * assertAllWindowTitles ( pattern  )
* assertNotAllWindowTitles ( pattern )
* verifyAllWindowTitles ( pattern )
* verifyNotAllWindowTitles ( pattern )
* waitForAllWindowTitles ( pattern )
* waitForNotAllWindowTitles ( pattern )
 
storeAttribute attributeLocator variableName * assertAttribute ( attributeLocator, pattern  )
* assertNotAttribute ( attributeLocator, pattern )
* verifyAttribute ( attributeLocator, pattern )
* verifyNotAttribute ( attributeLocator, pattern )
* waitForAttribute ( attributeLocator, pattern )
* waitForNotAttribute ( attributeLocator, pattern )
 
storeAttributeFromAllWindows attributeName variableName * assertAttributeFromAllWindows ( attributeName, pattern  )
* assertNotAttributeFromAllWindows ( attributeName, pattern )
* verifyAttributeFromAllWindows ( attributeName, pattern )
* verifyNotAttributeFromAllWindows ( attributeName, pattern )
* waitForAttributeFromAllWindows ( attributeName, pattern )
* waitForNotAttributeFromAllWindows ( attributeName, pattern )
 
storeBodyText variableName   * assertBodyText ( pattern  )
* assertNotBodyText ( pattern )
* verifyBodyText ( pattern )
* verifyNotBodyText ( pattern )
* waitForBodyText ( pattern )
* waitForNotBodyText ( pattern )
 
storeConfirmation variableName   * assertConfirmation ( pattern  )
* assertNotConfirmation ( pattern )
* verifyConfirmation ( pattern )
* verifyNotConfirmation ( pattern )
* waitForConfirmation ( pattern )
* waitForNotConfirmation ( pattern )
 
storeCookie variableName   * assertCookie ( pattern  )
* assertNotCookie ( pattern )
* verifyCookie ( pattern )
* verifyNotCookie ( pattern )
* waitForCookie ( pattern )
* waitForNotCookie ( pattern )
 
storeCookieByName name variableName * assertCookieByName ( name, pattern  )
* assertNotCookieByName ( name, pattern )
* verifyCookieByName ( name, pattern )
* verifyNotCookieByName ( name, pattern )
* waitForCookieByName ( name, pattern )
* waitForNotCookieByName ( name, pattern )
 
storeCursorPosition locator variableName * assertCursorPosition ( locator, pattern  )
* assertNotCursorPosition ( locator, pattern )
* verifyCursorPosition ( locator, pattern )
* verifyNotCursorPosition ( locator, pattern )
* waitForCursorPosition ( locator, pattern )
* waitForNotCursorPosition ( locator, pattern )
 
storeElementHeight locator variableName * assertElementHeight ( locator, pattern  )
* assertNotElementHeight ( locator, pattern )
* verifyElementHeight ( locator, pattern )
* verifyNotElementHeight ( locator, pattern )
* waitForElementHeight ( locator, pattern )
* waitForNotElementHeight ( locator, pattern )
 
storeElementIndex locator variableName * assertElementIndex ( locator, pattern  )
* assertNotElementIndex ( locator, pattern )
* verifyElementIndex ( locator, pattern )
* verifyNotElementIndex ( locator, pattern )
* waitForElementIndex ( locator, pattern )
* waitForNotElementIndex ( locator, pattern )
 
storeElementPositionLeft locator variableName * assertElementPositionLeft ( locator, pattern  )
* assertNotElementPositionLeft ( locator, pattern )
* verifyElementPositionLeft ( locator, pattern )
* verifyNotElementPositionLeft ( locator, pattern )
* waitForElementPositionLeft ( locator, pattern )
* waitForNotElementPositionLeft ( locator, pattern )
 
storeElementPositionTop locator variableName * assertElementPositionTop ( locator, pattern  )
* assertNotElementPositionTop ( locator, pattern )
* verifyElementPositionTop ( locator, pattern )
* verifyNotElementPositionTop ( locator, pattern )
* waitForElementPositionTop ( locator, pattern )
* waitForNotElementPositionTop ( locator, pattern )
 
storeElementWidth locator variableName * assertElementWidth ( locator, pattern  )
* assertNotElementWidth ( locator, pattern )
* verifyElementWidth ( locator, pattern )
* verifyNotElementWidth ( locator, pattern )
* waitForElementWidth ( locator, pattern )
* waitForNotElementWidth ( locator, pattern )
 
storeEval script variableName * assertEval ( script, pattern  )
* assertNotEval ( script, pattern )
* verifyEval ( script, pattern )
* verifyNotEval ( script, pattern )
* waitForEval ( script, pattern )
* waitForNotEval ( script, pattern )
 
storeExpression expression variableName * assertExpression ( expression, pattern  )
* assertNotExpression ( expression, pattern )
* verifyExpression ( expression, pattern )
* verifyNotExpression ( expression, pattern )
* waitForExpression ( expression, pattern )
* waitForNotExpression ( expression, pattern )
 
storeHtmlSource variableName   * assertHtmlSource ( pattern  )
* assertNotHtmlSource ( pattern )
* verifyHtmlSource ( pattern )
* verifyNotHtmlSource ( pattern )
* waitForHtmlSource ( pattern )
* waitForNotHtmlSource ( pattern )
 
storeLocation variableName   * assertLocation ( pattern  )
* assertNotLocation ( pattern )
* verifyLocation ( pattern )
* verifyNotLocation ( pattern )
* waitForLocation ( pattern )
* waitForNotLocation ( pattern )
 
storeMouseSpeed variableName   * assertMouseSpeed ( pattern  )
* assertNotMouseSpeed ( pattern )
* verifyMouseSpeed ( pattern )
* verifyNotMouseSpeed ( pattern )
* waitForMouseSpeed ( pattern )
* waitForNotMouseSpeed ( pattern )
 
storePrompt variableName   * assertPrompt ( pattern  )
* assertNotPrompt ( pattern )
* verifyPrompt ( pattern )
* verifyNotPrompt ( pattern )
* waitForPrompt ( pattern )
* waitForNotPrompt ( pattern )
 
storeSelectedId selectLocator variableName * assertSelectedId ( selectLocator, pattern  )
* assertNotSelectedId ( selectLocator, pattern )
* verifySelectedId ( selectLocator, pattern )
* verifyNotSelectedId ( selectLocator, pattern )
* waitForSelectedId ( selectLocator, pattern )
* waitForNotSelectedId ( selectLocator, pattern )
 
storeSelectedIds selectLocator variableName * assertSelectedIds ( selectLocator, pattern  )
* assertNotSelectedIds ( selectLocator, pattern )
* verifySelectedIds ( selectLocator, pattern )
* verifyNotSelectedIds ( selectLocator, pattern )
* waitForSelectedIds ( selectLocator, pattern )
* waitForNotSelectedIds ( selectLocator, pattern )
 
storeSelectedIndex selectLocator variableName * assertSelectedIndex ( selectLocator, pattern  )
* assertNotSelectedIndex ( selectLocator, pattern )
* verifySelectedIndex ( selectLocator, pattern )
* verifyNotSelectedIndex ( selectLocator, pattern )
* waitForSelectedIndex ( selectLocator, pattern )
* waitForNotSelectedIndex ( selectLocator, pattern )
 
storeSelectedIndexes selectLocator variableName * assertSelectedIndexes ( selectLocator, pattern  )
* assertNotSelectedIndexes ( selectLocator, pattern )
* verifySelectedIndexes ( selectLocator, pattern )
* verifyNotSelectedIndexes ( selectLocator, pattern )
* waitForSelectedIndexes ( selectLocator, pattern )
* waitForNotSelectedIndexes ( selectLocator, pattern )
 
storeSelectedLabel selectLocator variableName * assertSelectedLabel ( selectLocator, pattern  )
* assertNotSelectedLabel ( selectLocator, pattern )
* verifySelectedLabel ( selectLocator, pattern )
* verifyNotSelectedLabel ( selectLocator, pattern )
* waitForSelectedLabel ( selectLocator, pattern )
* waitForNotSelectedLabel ( selectLocator, pattern )
 
storeSelectedLabels selectLocator variableName * assertSelectedLabels ( selectLocator, pattern  )
* assertNotSelectedLabels ( selectLocator, pattern )
* verifySelectedLabels ( selectLocator, pattern )
* verifyNotSelectedLabels ( selectLocator, pattern )
* waitForSelectedLabels ( selectLocator, pattern )
* waitForNotSelectedLabels ( selectLocator, pattern )
 
storeSelectedValue selectLocator variableName * assertSelectedValue ( selectLocator, pattern  )
* assertNotSelectedValue ( selectLocator, pattern )
* verifySelectedValue ( selectLocator, pattern )
* verifyNotSelectedValue ( selectLocator, pattern )
* waitForSelectedValue ( selectLocator, pattern )
* waitForNotSelectedValue ( selectLocator, pattern )
 
storeSelectedValues selectLocator variableName * assertSelectedValues ( selectLocator, pattern  )
* assertNotSelectedValues ( selectLocator, pattern )
* verifySelectedValues ( selectLocator, pattern )
* verifyNotSelectedValues ( selectLocator, pattern )
* waitForSelectedValues ( selectLocator, pattern )
* waitForNotSelectedValues ( selectLocator, pattern )
 
storeSelectOptions selectLocator variableName * assertSelectOptions ( selectLocator, pattern  )
* assertNotSelectOptions ( selectLocator, pattern )
* verifySelectOptions ( selectLocator, pattern )
* verifyNotSelectOptions ( selectLocator, pattern )
* waitForSelectOptions ( selectLocator, pattern )
* waitForNotSelectOptions ( selectLocator, pattern )
 
storeSpeed variableName   * assertSpeed ( pattern  )
* assertNotSpeed ( pattern )
* verifySpeed ( pattern )
* verifyNotSpeed ( pattern )
* waitForSpeed ( pattern )
* waitForNotSpeed ( pattern )
 
storeTable tableCellAddress variableName * assertTable ( tableCellAddress, pattern  )
* assertNotTable ( tableCellAddress, pattern )
* verifyTable ( tableCellAddress, pattern )
* verifyNotTable ( tableCellAddress, pattern )
* waitForTable ( tableCellAddress, pattern )
* waitForNotTable ( tableCellAddress, pattern )
 
storeText locator variableName * assertText ( locator, pattern  )
* assertNotText ( locator, pattern )
* verifyText ( locator, pattern )
* verifyNotText ( locator, pattern )
* waitForText ( locator, pattern )
* waitForNotText ( locator, pattern )
 
storeTitle variableName   * assertTitle ( pattern  )
* assertNotTitle ( pattern )
* verifyTitle ( pattern )
* verifyNotTitle ( pattern )
* waitForTitle ( pattern )
* waitForNotTitle ( pattern )
 
storeValue locator variableName * assertValue ( locator, pattern  )
* assertNotValue ( locator, pattern )
* verifyValue ( locator, pattern )
* verifyNotValue ( locator, pattern )
* waitForValue ( locator, pattern )
* waitForNotValue ( locator, pattern )
 
storeWhetherThisFrameMatchFrameExpression target variableName * assertWhetherThisFrameMatchFrameExpression ( currentFrameString, target )
* assertNotWhetherThisFrameMatchFrameExpression ( currentFrameString, target )
* verifyWhetherThisFrameMatchFrameExpression ( currentFrameString, target )
* verifyNotWhetherThisFrameMatchFrameExpression ( currentFrameString, target )
* waitForWhetherThisFrameMatchFrameExpression ( currentFrameString, target )
* waitForNotWhetherThisFrameMatchFrameExpression ( currentFrameString, target )
 
storeWhetherThisWindowMatchWindowExpression currentWindowString target * assertWhetherThisWindowMatchWindowExpression ( currentWindowString, target )
* assertNotWhetherThisWindowMatchWindowExpression ( currentWindowString, target )
* verifyWhetherThisWindowMatchWindowExpression ( currentWindowString, target )
* verifyNotWhetherThisWindowMatchWindowExpression ( currentWindowString, target )
* waitForWhetherThisWindowMatchWindowExpression ( currentWindowString, target )
* waitForNotWhetherThisWindowMatchWindowExpression ( currentWindowString, target )
 
storeXpathCount xpath variableName * assertXpathCount ( xpath, pattern  )
* assertNotXpathCount ( xpath, pattern )
* verifyXpathCount ( xpath, pattern )
* verifyNotXpathCount ( xpath, pattern )
* waitForXpathCount ( xpath, pattern )
* waitForNotXpathCount ( xpath, pattern )
 
storeAlertPresent variableName   * assertAlertPresent ( )
* assertAlertNotPresent ( )
* verifyAlertPresent ( )
* verifyAlertNotPresent ( )
* waitForAlertPresent ( )
* waitForAlertNotPresent ( )
 
storeChecked locator variableName * assertChecked ( locator )
* assertNotChecked ( locator )
* verifyChecked ( locator )
* verifyNotChecked ( locator )
* waitForChecked ( locator )
* waitForNotChecked ( locator )
 
storeConfirmationPresent variableName   * assertConfirmationPresent ( )
* assertConfirmationNotPresent ( )
* verifyConfirmationPresent ( )
* verifyConfirmationNotPresent ( )
* waitForConfirmationPresent ( )
* waitForConfirmationNotPresent ( )
 
storeCookiePresent name variableName * assertCookiePresent ( name )
* assertCookieNotPresent ( name )
* verifyCookiePresent ( name )
* verifyCookieNotPresent ( name )
* waitForCookiePresent ( name )
* waitForCookieNotPresent ( name )
 
storeEditable locator variableName * assertEditable ( locator )
* assertNotEditable ( locator )
* verifyEditable ( locator )
* verifyNotEditable ( locator )
* waitForEditable ( locator )
* waitForNotEditable ( locator )
 
storeElementPresent locator variableName * assertElementPresent ( locator )
* assertElementNotPresent ( locator )
* verifyElementPresent ( locator )
* verifyElementNotPresent ( locator )
* waitForElementPresent ( locator )
* waitForElementNotPresent ( locator )
 
storeOrdered locator1 locator2/variableName * assertOrdered ( locator1, locator2 )
* assertNotOrdered ( locator1, locator2 )
* verifyOrdered ( locator1, locator2 )
* verifyNotOrdered ( locator1, locator2 )
* waitForOrdered ( locator1, locator2 )
* waitForNotOrdered ( locator1, locator2 )
 
storePromptPresent variableName   * assertPromptPresent ( )
* assertPromptNotPresent ( )
* verifyPromptPresent ( )
* verifyPromptNotPresent ( )
* waitForPromptPresent ( )
* waitForPromptNotPresent ( )
 
storeSomethingSelected selectLocator variableName * assertSomethingSelected ( selectLocator )
* assertNotSomethingSelected ( selectLocator )
* verifySomethingSelected ( selectLocator )
* verifyNotSomethingSelected ( selectLocator )
* waitForSomethingSelected ( selectLocator )
* waitForNotSomethingSelected ( selectLocator )
 
storeTextPresent pattern variableName * assertTextPresent ( pattern )
* assertTextNotPresent ( pattern )
* verifyTextPresent ( pattern )
* verifyTextNotPresent ( pattern )
* waitForTextPresent ( pattern )
* waitForTextNotPresent ( pattern )
 
storeVisible locator variableName * assertVisible ( locator )
* assertNotVisible ( locator )
* verifyVisible ( locator )
* verifyNotVisible ( locator )
* waitForVisible ( locator )
* waitForNotVisible ( locator )
 

by chikkun