Seleniumの使い方

ひさしぶりにSeleniumを使ったら、いろいろ忘れていたのでメモ。

まずリンク:

全体に

Seleniumはブラウザ上の挙動をテストできるので、JavaScriptを含めて全体的な挙動をテストするのに向いている。だが、テストを書くのはけっこう大変なので、サーバーサイドのテストで書けることは、そっちで対応するほうが楽ができる。Ajaxバリバリのサイトなんかだと、Seleniumでないとテストできない部分が大量に出てくるので、ありがたい。Seleniumじゃなくても書けるテストをがんばってSeleniumで書くのは、いくつか問題がある。

  • 時間がかかる。
    • テストを書くのにかかる時間と、テストを実行するのにかかる時間。
  • つかれる。
  • あとでメンテするのがけっこう大変。テストを見ても、なにをしているのかわかりづらい。
    • コメントを思いっきり入れておくといいようだ。
    • Selenium RC(ドライブモード)を使うと、いろいろ改善できるはず。

ドキュメントについて

まずちょっと触ってみて、Seleniumの感覚がつかめたら、ドキュメントを一読するべき。特に以下の部分は、知らないとえらく苦労する。

  • locatorの書き方
    • id, name
    • xpath
      • これはIEだとやたら遅いので注意。
    • css
  • テキストマッチの記法
    • glob
    • exact
      • 完全一致。
      • 複数のタグにまたがってテキストをscrapeした結果は、ブラウザによって異なってしまうので注意。
    • regexp

SeleniumIDE

テストケースを作るのに一番楽なのは、SeleniumIDE(Firefox専用)を使って、一連の動作と確認(assert/verify)を記録すること。テストケースがさくさく作れるが、以下の点に注意。SeleniumIDEは0.8.7。

  • SPANのクリックを記録してくれない。
  • 非同期処理があるときには、後でpauseやwaitForXxxを追加する必要がある。
  • 何をしたのか、コメントを積極的に追加する。
  • locatorにXPathを使いたがるので、適宜手直しをすること。

またSeleniumIDEでテストの実行もできるが、ブラウザ上で(Selenium Coreを使って)実行したときと結果が変わってしまう場合がある。とくにイベントの発生などをしていると、SeleniumIDEではうまく動かない場合がある。

結果を待って確認する

ページを普通に遷移するものは、clickAndWaitが使えるが、ユーザのアクションに応じてページを動的に書き換えるものは、そうは行かない。特にAjaxで非同期に書き換えるものは、書き換わるまで待つ必要が出てくる。待つにはpauseかwaitForXxxを使えるが、pauseでは環境によって間に合わない場合がありうる。またwaitForだと、CPUに負荷がかかるのでテストが不要に遅くなることがある。(特にwaitForXxxでlocatorでXPathを使うと、IEでは処理が以上に遅くなり、たいていタイムアウトしてしまう。)

Seleniumテスタビリティ

locatorとしてはidが一番使いやすいので、ターゲットのHTMLにはidをやたらめったら使うほうがよい。もっとも、テストを書きながら必要に応じて付加していくという手もある。当然だがidは重複しないようにしなくてはいけないが、特に以下の点に気をつける。

  • 画面上の部品につけるときは、その部品を複数回使う可能性がある。
  • 一覧など、複数表示するようなものには、プライマリキーなどユニークなものを付加したidをつけるとよい。プライマリキーが数字以外の場合は、きちんとエスケープすること。

ユーザーインターフェースの設計としても、テストしやすいものとしにくいものがある。上で書いた、ページの一部分を非同期に書き換えるものは、待ちの処理が煩雑になる。

テストの可読性

Seleniumのテストをあとから読もうとすると、なにをしているのかわからないことが多い。できるだけコメントを入れたほうがよい。わたしは以下の観点でコメントを入れている。

  • どの機能のどんな側面をテストしているのか
  • どんな操作か(ユーザーのアクション)
  • なにを確認しているのか(assert/verify)

この3点は階層構造にできるので、SeleniumIDEで記録せずに手でテストを書くときは、この階層でまずコメントをすべて書いてしまい、そこにコマンドを追加していく。たとえば、まず以下のようにテスト内容を日本語で書く。

○日記を書く
ログインする。
「日記を書く」をクリックする。
編集欄に入力する。
プレビュータブをクリックする。
・正しく表示されること。
編集タブをクリックする。
・入力したものがそのまま残っていること。
登録するをクリックする。
・書いた日記のURLに遷移すること。
・日記が表示されること。

これをTABLEタグに入れてコメントにする。

<tr><td colspan="3">○日記を書く</td></tr>
<tr><td colspan="3">ログインする。</td></tr>
<tr><td colspan="3">「日記を書く」をクリックする。</td></tr>
<tr><td colspan="3">編集欄に入力する。</td></tr>
<tr><td colspan="3">プレビュータブをクリックする。</td></tr>
<tr><td colspan="3">・正しく表示されること。</td></tr>
<tr><td colspan="3">編集タブをクリックする。</td></tr>
<tr><td colspan="3">・入力したものがそのまま残っていること。</td></tr>
<tr><td colspan="3">登録するをクリックする。</td></tr>
<tr><td colspan="3">・書いた日記のURLに遷移すること。</td></tr>
<tr><td colspan="3">・日記が表示されること。</td></tr>

ここまで書いてから、あらためてテスト用のコマンドを埋め込んでいく。そうすると後で読みやすくなる。

コメントのつけかたやテストの書き方は、いろいろ改善のアイデアがある。やってみたい。もっともRCを使うと劇的に改善したり、しないかしら。

Seleniumのよいところ

これがなくてはできないことが、できる。ブラウザの挙動を、JavaScriptまで含めてテストするためのコードが書ける、ということ。使いにくいとか、しんどいとか、コストがかかるとかの問題は二の次。というかそれは「運用で対応」というか、工夫と他のツール類で解決すべき問題。