More than 1 year has passed since last update.

アナウンス

Selenium 談話会 in Slack

  • 2015/春から「Selenium 談話会 in Slack」というものをはじめました
  • Slack(チャット)を使って日々の困りごとなどを同士とリアルタイムで情報交換することができます
    • 登録されているユーザは2015/06/25時点で35名
  • 月1回程度でチャット上に集まってテーマを決めて話をしています
  • 詳細、参加方法などは上記リンク先に書いています

日本Seleniumユーザーコミュニティ

  • 日本Seleniumユーザーコミュニティは、Seleniumに関する分からないこと・困ったことについてユーザー同士で助け合うグループです

はじめに

  • Selenium歴7年目になり、ノウハウがたくさん溜まってきたのでここにまとめます
  • Seleniumを使われる方に役に立つ情報がきっとあると思います
    • 「使えそうだ!」と思って頂けたらぜひストックしてください
    • 困ったときに、ここをみて頂けたら嬉しいです!
  • もちろん、これからSeleniumを触る方にも読んで頂きたいです
  • ここでは、Selenium IDEとSelenium Webdriverの使い方や気をつけなければならないことを書いていきます
  • Seleniumに関係することも書いていきます

今までに経験したSeleniumのテストツール

  • Selenium IDE
  • Selenium RC(Selenium1)
  • Selenium Webdriver(Selenium2)

Selenium IDE

  • Firefoxのアドオン
  • 簡単かつ手軽に使えるのが特徴
  • 初心者でも使える(私は今でも時々使っています)
  • 起動したら自動記録モードで立ち上がるため、ボタンを押したりテキスト入力したりするだけでテストコードが自動で出力される
  • テストコードはワンクリックで再生可能
  • Javascriptも実行できるので割といろんなことができちゃいます!!
  • Firebugを一緒にインストールすることをお勧めします
    • 要素を覗いたりするのがとても便利です

Selenium RC(Selenium1)

  • Selenium IDEで作ったテストをコマンドラインからドバっと実行できる
  • javaコマンドで実行(要javaのインストール)
  • 実行結果もHTMLのレポートとして出力可能
  • ただ、現在はSelenium Webdriverが定着してきているので使っている人は少ないのかなと

Selenium Webdriver(Selenium2)

  • Selenium公式ドキュメントにも「Selenium 1.0 + WebDriver = Selenium 2.0」とあるように改良された激アツ(ゼブラ柄)なやつ
  • ここにも書いてあるようにSeleniumのテストコード自体がたくさんの言語で書けます
    • 私はRubyで書いています
  • Cucumberと組み合わせてテストを日本語書くこともできます
  • さらに、Capybaraと組み合わせることもできます

Selenium IDE

インストール

  • ダウンロードサイトのDownload latest released version X.X.Xのところからダウンロードし、Firefoxを再起動する

起動

  • 「ツール」▶︎「Selenium IDE」で起動
  • 起動時は「記録モード」になっている

使い方

  • クリックしたり、テキスト入力したりすると以下のように自動でコマンドが出力される
  • 例)
    • qiitaページでseleniumを検索
    • seleniumタグをフォローする
    • qiita.png
  • これだけはおさえておきたい!Selenium IDEのコマンドによく使うコマンドを詳解しています
  • Seleniumの主要コマンドは"やること"+"何を"で組み合わさっていることに気づけば自然と覚えられる
  • 例)
    • "やること"の部分はstore/verify/assert
    • "何を"の部分はTitle/Text/Alert/CssCount/...etc

verifyとassertの使い分け

  • 上で、"やること"の部分を3つあげたがstoreは変数に格納する
  • verifyとassert何が違うの?ということで、実際にコマンドを実行しても案外違いに気づかないものかもしれない
  • どちらも検証するコマンドだが、verifyコマンドは検証結果が失敗していても次のコマンドが実行されるが、assertコマンドは失敗したら即終了
コマンド 対象 説明
store Qiita Q ${Q}に"Qiita"を格納する
verifyText ${Q} キータ ${Q}は"キータ"ではないので失敗する
echo ${Q} (指定なし) Qiitaがコンソールに表示される
assertText ${Q} キータ ${Q}は"キータ"ではないので失敗する
echo ${Q} (指定なし) コマンド自体が実行されない
  • 使い分けとしては失敗したらそれ以降はテストする意味がない場合にはassertコマンド
    • 余分な検証時間をとらなくて済むので
  • 失敗してもその他のテストは実行しておきたいのでという場合はverifyコマンド
  • 用途に応じて使い分けるのがよいでしょう

ちょっとした応用

verifyXXXXなどはワイルドカードでも検証可能

  • 「*(半角アスタリスク)」がワイルドカードとして扱われる
コマンド 対象 説明
verifyTitle *Qiita (指定なし) ページタイトル「ホーム - Qiita」の後方一致
verifyText css=#main .header h2 プログラミング知識を共有* 「プログラミング知識を共有しよう。」の前方一致

javascript式を使う

  • javascript式を挿入する方法は2つ
    • XXXXEvalコマンドを使う
    • javascript式だということを明示的に書く
  • XXXXEvalの書き方だと対象には"javascript{}"は要らないので注意!!
コマンド 対象 説明
storeEval 1+2+3 hoge ${hoge}に6が格納される
store javascript{1+2+3+4} foo ${foo}に10が格納される
  • if文や関数なども使える
    • storedVars.変数名でjavascript内では呼び出し可能。その他は${変数名}
コマンド 対象 説明
verifyEval if(storedVars.hoge > 5){true;}else{false;} true ${hoge}が5以下なら[error] Actual value 'false' did not match 'true'

別タブで開くことの検証

  • 別タブ/ウィンドウで開くことのテストは可能
  • ボタン等をクリックすると新しいウィンドウが「ぽこっ」と出て、waitForPopUpなりselectWindowなりをかましてカレントウィンドウにするとか
  • ただ、できればそのやり方はしないほうが良い
    • ウィンドウが立ち上がるまでに時間がかかって不安定のなテストの原因となりかねない
    • そもそも別タブ/ウィンドウで開くことはHTMLレベルで判断でき、ブラウザの機能として提供されているため、わざわざSeleniumでその挙動まで見る必要はない

このように検証すれば良い

コマンド 対象 説明
verifyAttribute css=a@target _blank aタグのtarget属性の値が'_blank'になっていることの検証
storeAttribute a@href link 別ウィンドウで開くページのURLを格納
open ${link} (指定なし)
verifyTitle Qiita - ホーム (指定なし) 以上のコマンドで別ウィンドウで開くこと+開いたページのタイトルの検証が擬似的にできる

Whileループ

  • 何回も同じ処理をさせたい場合に使えるワザをご紹介
  • 手順はuser-extensions.jsの指定とテスト記述のみ

user-extensions.jsの指定

  • user-extensions.jsを好きなところに配置する
  • Selenium IDEを起動後、「オプション」▶︎「設定」に「一般」進む
  • 「Selenium Core 拡張スクリプト(user-extensions.jsのパス)」欄に取得したuser-extensions.jsファイルのパスを入れる

Whileコマンドを使用しないでやるループ処理

テスト作成

コマンド 対象 説明
store 0 i カウンタを0に設定
while storedVars.i++ < 50 (指定なし) 50回繰り返しをする
echo ${i} (指定なし) whileとendWhileコマンドの間にやらせたい処理を書く(今の例はカウンタを表示)
endWhile (指定なし) (指定なし)

SelBlocksを使った条件分岐やループ処理

  • SeleniumIDE × SelBlocks活用事例を参照してください
  • Firefoxのアドオンをインストールするだけでよく、上で書いた拡張スクリプトやタイマー制御よりオススメです
  • Selenium IDEをお使いの方であれば、一度は試したもうがよい そんな代物でした!

SeleniumIDEを使って「自動テストすげ〜」と言わせる方法

Selenium Webdriver

【初心者向け】いち早くSeleniumWebdriverを体験してみたい方

Cucumberを利用する

  • Cucumberを使うことで、Gherkin書式(Cucumberの特徴である、システムの振る舞いを記述するための自然言語に近い書式)でテストを作成することが出来る
  • Gherkin書式は、テストシナリオとステップを以下のように2つのファイルに分割して記述する
  • 仕様記述のfeatureファイル(xxx.feature)
    • アプリケーションの機能(フィーチャ)を記述する
    • 非実装者や日本語でもわかりやすい表現で記述できる
  • 具体的なステップの中身を記述するstepファイル(xxx_steps.rb)
    • テストシナリオの手順 (ステップ) の定義を記述する
    • 具体的なコマンドやコードをずらずらと記述する

☆知っておきたいワザやノウハウ☆

Capybaraを利用する

  • Capybaraの説明はCapybaraのREADME 意訳が参考になるかと
    • コマンドについての説明も書かれています

☆知っておきたいワザやノウハウ☆

  • NoMethodError: undefined method `visit'といわれたら・・・
  • というか何回か書き忘れて何度も目にして「また、こいつか」となってましたw
  • Capybaraを認識していないので下記サイトのような記述を追加してあげてください

テスト実行前にブラウザのキャッシュをクリアする

  • テストの失敗事例の1つに取得しているjavascriptファイルやCSSファイル、faviconが期待通りに取れていないということがありました
  • 一見要素のロードに失敗した(表示がされるまで待てなかった)のかと思いましたが、何回か実行しても待機時間を挟んでも失敗のまま
  • ちょうど失敗の原因がjavascriptの処理だったので、もしかしてと思いキャッシュを消してみると「ビンゴ!」
  • 取得していたjavascriptコードが古かったのです

☆知っておきたいワザやノウハウ☆

その他

☆知っておきたいワザやノウハウ☆

Seleniumを実行するための環境構築

日本語の文字化け対策

  • スクリンショットを保存してみると、日本語が□(とうふ)のように化けてる現象が起きた場合は日本語フォントをいれてやる必要があります
  • @u_s_k さんが記事を書かれていたのでご紹介
    • ※ CentOSのバージョンによって異なる

CentOS6.4

$ sudo yum groupinstall "Japanese Support"

CentOS6.6(minimal)

$ sudo yum install ipa-pgothic-fonts.noarch

Ubuntu12.04

$ wget -q https://www.ubuntulinux.jp/ubuntu-ja-archive-keyring.gpg -O- | sudo apt-key add -
$ wget -q https://www.ubuntulinux.jp/ubuntu-jp-ppa-keyring.gpg -O- | $ sudo apt-key add -
$ sudo wget https://www.ubuntulinux.jp/sources.list.d/quantal.list -O /etc/apt/sources.list.d/ubuntu-ja.list
$ sudo apt-get update
$ sudo apt-get install ubuntu-defaults-ja

セレクタ

  • Seleniumと切っても切りはなせないのが要素の指定
    • 投稿記事のタイトルが「全国のSeleniumist必読」であること
    • 投稿者名が「oh_rusty_nail」など、容易にその場面はやってくる
  • セレクタの指定はCSSとXPATHどちらでも可能だが、「まぜるな危険」は漂白剤にとどまっている問題ではないと思う
    • その理由として、単に統一されていた方が読みやすい
    • 複数人での開発で書き方が様々なんて良くはないでしょう(私のところではCSSで統一させてます)
  • CSSセレクタについては[覚え書き] CSS再入門~セレクタ~が参考になると思います

☆知っておきたいワザやノウハウ☆

エラーとその対処法

  • これは、みなさんが一番興味を抱かれているところではないでしょうか
  • 私が持っているノウハウをご紹介します

①失敗しているを原因を追いやすくしましょう

最低限の検証は入れておきましょう

  • 具体的な例で言うと、あるページを開いてあるボタンをクリックするテストで"Element not found"と言われて失敗したとき
  • これって以下のどれで失敗したか分からないですよね
    • ①Seleniumがページのロードに失敗でクリック対象の要素が取得できなかった
    • ②現在開かれているページが、期待しているページと異なるページを開いていた
    • ③ただ、単にユーザがクリックするボタンの指定(セレクタなど)を間違えていた
  • 以下のようにタイトル検証を一行挟むだけで、①と②の線はすぐに明らかになる
  • ③はタイトルが期待通りであれば要素の指定ミスが濃厚になる
  • (勿論、クリック対象の要素のロードがまだという線もないわけではない)
#Before
visit hoge_url
find(element).click

#After
visit hoge_url
page.should have_title(title) # <= タイトル検証
find(element).click

エラーが起こったらスクリーンショットで証拠写真をパシャ

  • hookスクリプトに失敗時にスクリーンショットを残すように仕込んでおく
    • この動かぬ証拠がエラーの原因判明におおいに活躍する
support/hook.rb
...
After do |scenario|
  if scenario.failed?
    screenshot_name = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
    page.save_screenshot screenshot_name+'.png'
  end 
end
...

②SeleniumのTimeoutErrorをできるだけ発生しないようにするコツ

TimeoutErrorはどんなときに起きるのか

  • TimeoutErrorはは、ページを開いたらロード中のままで応答が返ってこなくなり発生というケースが多い
  • 実際にブラウザを立ち上げて実行してみると、"くるくる"回ってて一向に応答がないではないかという場面を見るのは少なくないのではないかと

Timeoutの時間をのばす!?

  • Timeoutするまでの時間を設定できる
  • 正直短くするのは意味があるかもしれないが、長くするのは。。。
  • 例えば、10秒待ってダメならお亡くなりになってくださいというテストを組むときは、短くすることが時間短縮につながるので有効かもしれない
  • しかし、デフォルトの時間ではロードしきれないからのばすというのは考えものだ
  • というのはデフォルトのTimeoutErrorは発生するまでの待機時間は60秒もあるからだ
  • もし、"ただクソ重いだけでめちゃめちゃ待てば応答のある"のサイトでテストを考える場合は以下のようにTimeoutの時間を設定してください

Timeoutを撃退させた事例

ページを開いた後にリロードとスリープをかませる

  • 失敗していた箇所
    • 指定した要素は表示されているが、ロード中で"くるくる"回っているためここで期待している要素数1を取得できていない
...
visit hoge_url
page.all(element).count.should == 1 # <= ここで失敗
...
  • Seleniumに限らず、普段ロード中で応答が返ってこなくなったときにリロードしたらロードが完了するケースを思い出した
  • wait_for_element_presentというメソッドを定義して以下のようにしてみたら非常に安定した
    • 実際、回してみると"Try reload and sleep"は1回程使われていた
    • max_wait_time, sleep_timeをカスタマイズして使ってみてください
...
visit hoge_url
wait_for_element_present(element, 1, 120, 10) # <= 期待通りの要素数が取得できるまでリロード+10秒待機を最大12回行う
page.all(element).count.should == 1

def wait_for_element_present(element, element_count = 1, max_wait_time = 60, sleep_time = 10)
  if element
    cnt = max_wait_time / sleep_time
    cnt.times do |c|
      if page.all(element).count < element_count
        visit current_url
        sleep sleep_time
        puts "Try reload and sleep"
      end
    end
  else
    puts "Element not selected."
  end
end
...

countオプション付きで要素検証する

  • 要素検証のときに以下のように期待する要素数を以下のようにして書いておく
  • countオプション指定するとCapybara.default_wait_timeの分だけ待機する
  • 待機間隔、試行回数などカスタマイズしないのであればこれで十分だと思います
page.all(element, count: 1)
all(selector, count: 1, wait: 10)

( @hanachin_ さんから頂いたコメントより追記 2014/10/08 )

別タブで開くリンクのクリックで発生するTimeoutErrorの撃退法

③Selenium+JenkinsでのCIをできるだけコケないようにする

④ブラウザキャッシュが残っていて、ある環境下で失敗し続ける

  • 前節のSeleniumWebdriverの説明でも触れましたが、ブラウザキャッシュが残っていた(有効にしている)ためある環境ではテストで失敗するという現象はなくはないことだとおもいます
  • もちろんどんなテストをしているかにもよりますが
  • Seleniumでブラウザを自動操縦するときに使っているブラウザのプロファイルに設定をいれることでこの問題は解決できます
  • 【Selenium】Firefoxのキャッシュを無効にしてエラーを未然に防ぐに対策を書いています

⑤テストを実行しているときに「Modal dialog present」エラーが出た

解析のやり方

  • まず、ヘッドレス(ブラウザを表に出さないようにした状態)で実行しているのであれば、表示させるように変えて下さい
  • 例えば、実行コマンドに$bundle exec rake cucumber NO_HEADLESS=trueのようなrakeコマンド引数でON/OFF切替できるようにしています
    • 実際、テストを作るときには実際にブラウザの挙動を見ながら作った方が作りやすいことも多々あります
    • CIで実行するときには当然ヘッドレス実行で問題ないのですがね
  • この解析でブラウザ内のダイアログやポップアップが表示されていることにより、Seleniumがブラウザを操縦できなくなっているのか判明することがあります
  • 参考までに、ブラウザ外であれば、以下のようなダイアログ(ポップアップ)を見たことがあります
    • javaの自動アップデートの確認
    • サーバー証明書絡みの確認
  • driverを確認してみて下さい

解決した対応例

IEの場合
  • テストの最中でダイアログが表示されていた模様
  • 対応1(だめなら対応2も)をすると出なくなった
    • 対応1:「インターネットオプション」→「セキュリティ」→「Webページが、制限されたプロトコルをアクティブコンテンツに使用することを許可する」でダイアログを表示するから有効にするに変更
    • 対応2:「ツール」→「インターネットオプション」 →「詳細設定」で「サーバー証明書の取り消しを確認する」のチェックをはずす
firefoxの場合
  • 現象 : 某SNSとのOAuthのテストでSNSログイン時にダイアログが表示されていた & ダイアログが取得できなかった
  • 原因 : current_driverが:airになっていた
  • 対応 : :firefoxにするとダイアログ自体が表示されなくなった

⑥waiting for evaluate.js load failedといわれる

⑦unable to obtain stable firefox connection in 60 secondsといわれる

事例A

  • 2014/09/04現在、Firefoxのバージョンを32.0にあげたところエラーが出るようになった
  • selenium-webdriverのバージョンは2.38.0
  • SeleniumIDEでは、立ち上げると画面が真っ白になるという現象が。。
    • 通常、Firefoxのバージョンをあげると、互換性のチェックが走り一緒にアドオンのバージョンもあがることが多い
  • 結局、31.0にバージョンを落とすとエラーはでなくなった
  • Selenium側がFirefox32.0にまだ対応していなかったのだろう

事例B

  • 結論からいうとパッケージの更新(yum update)が原因だった
  • Firefoxはちょっと古いバージョンがいれたかったため、yumリポジトリからyum installせず自力で入れた
  • yum updateでlibffiというパッケージが更新されていたためfirefox自体が起動しなくなっていた
$ firefox -x
XPCOMGlueLoad error for file /usr/local/firefox/libxul.so:
libffi.so.5: cannot open shared object file: No such file or directory
Couldn't load XPCOM.

⑧【おまけ】Facebookが絡みのエラー

Facebookからログアウト操作をするときにTimeoutErrorが発生する

  • ログアウト処理で応答が返ってこなくなることがあった
  • Facebookのログアウトする方法をCookie削除に変更したら安定した
    • SafariはCookieの削除が効かなかったので注意
...
visit "https://www.facebook.com/"
Capybara.current_session.driver.browser.manage.delete_all_cookies
...

Appium

Appiumとは

  • 公式サイト:http://appium.io/
    • 公式サイトからAppiumの紹介ビデオ(Youtube)を見ることができるので、初めての方はそれをみると掴みやすいかもしれません
  • Appiumとは「モバイルアプリを対象としたテスト自動化のためのフレームワーク」
  • Seleniumの流儀でモバイルアプリのテスト自動化のコードを書くことができるのが特徴
  • Seleniumを使ったテスト自動化経験のあるエンジニアにとっては、比較的簡単にモバイルアプリのテスト自動化のコードを書くことができます

☆知っておきたいワザやノウハウ☆

関連するツールやサービス

Jenkins

  • JenkinsはCIツールではかなり上位にランクインするツールではないだろうかと個人的には思っています
  • 簡単に導入できるし、用途もかなりあっていろいろ使えちゃうので
  • また、プラグインも沢山提供されているので自分の使い方にあったものを入れていけばかなり便利になります

☆知っておきたいワザやノウハウ☆

TravisCI

  • TravisCIはクラウド上でCIできるサービスです
    • .travis.ymlという1つのファイルを配置するだけで始められます
  • TravisCI上でもSeleniumのテストは当然実行可能です
  • xvfb,Firefoxも最初から入っています
  • 【TravisCI】【まとめ】高速化のためにした8つの工夫にまとめを書きました
    • TravisCIをご利用の方は是非読んで下さい♫ 損はさせません!!

☆知っておきたいワザやノウハウ☆

SauceLabs

TravisCI + SauceLabs

☆知っておきたいワザやノウハウ☆

BrowserStack

Watir

おわりに

  • ここにいろいろノウハウ書いていきました。今後もここを育てていく予定です
  • もっとこんな情報があります!等どしどし募集します!
  • お気軽に編集リクエストをください!
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.