前回、Robot Framework + Selenium2Libraryで、HTMLのフォームまわりをテストしてみました。
Robot Framework + Selenium2Libraryで、HTMLフォームまわりをテストする - メモ的な思考的な
今回は、Robot Framework + Selenium2Libraryで、HTML + JavaScriptまわりをテストしてみます。
2017/9/2追記
Selenium2Libraryですが、バージョン3からは SeleniumLibrary
へと名称が変更されています。詳しくはこちらに書きました。
RobotFrameworkのSelenium2Libraryの名前が、SeleniumLibraryへと変更されてた - メモ的な思考的な
なお、本文はSelenium2Libraryのままにしてあります。
2017/9/2追記ここまで
目次
環境
- Mac OS X 10.11.6
- Python 3.6.2
- Google Chrome 60.0.3112.78 (stable)
- ChromeDriver 2.31 (stable)
- RobotFramework 3.0.2
- Selenium2Library 1.8.1dev1
- GitHubから現在の最新版をインストール
- PyPIにある1.8.0では、Python3系だとエラーが出てインストールできない
- Selenium 3.4.3
- Bottle 0.12.13
Elementが出てくるまで待つ
<div id="show_delay"></div>
というHTMLに対し、
window.addEventListener("load", function () {
setTimeout(function(){
document.getElementById('show_delay').innerHTML = '<p id="hello">Hello, world!</p>'
}, 3000);
});
と、3秒後にp要素を追加するJavaScriptがあるとします。
この場合、Wait Until Page Contains Element
を使い、p要素が出てくるまで待機します。
Wait Until Page Contains Element | Selenium2Library
# p要素が出てくるまで待つ
wait until page contains element id=hello
# 出てきたら、p要素のテキストが正しいかを確認
element text should be id=hello Hello, world!
マウスオーバーすると出てくるElementをクリックする
<div id="on_mouse_area">このあたりをマウスオーバーするとボタンが見える
<button id="mouse_target" style="display: none;">
mouseoverのみ見える
</button>
</div>
というdisplay: none
なHTMLがあり、
var on_mouse_area = document.getElementById('on_mouse_area');
on_mouse_area.onmouseover = function () {
document.getElementById('mouse_target').style.display = 'block';
};
on_mouse_area.onmouseout = function () {
document.getElementById('mouse_target').style.display = 'none';
};
var mouse_target = document.getElementById('mouse_target');
mouse_target.onclick = function () {
window.location.href = '/'
};
と、マウスオーバー時に表示するJavaScriptがあるとします。
この場合、Mouse Over
を使いマウスオーバーした後、Click Element
します。
Mouse Over | Selenium2Library
# マウスオーバーする
mouse over id=on_mouse_area
# クリックする
click element id=mouse_target
スクロールしてクリックする
<div class="bottom" style="padding-top: 1200px">
<button id="bottom_button">下にあるボタン</button>
</div>
と、縦長のページの一番下にボタンがあるとします。
この場合、JavaScriptを実行するExecute Javascript
を使い、JavaScriptのwindow.scrollTo()
などを使います。
# スクロールする
Execute JavaScript window.scrollTo(0, 1200)
# クリックする
click element id=bottom_button
画面サイズを変更する
スクロールするとは関係ないですが、画面サイズについて、
- 現在の画面サイズを取得する
Get Window Size
- 画面サイズを変更する
Set Window Size
などがあります。
# 現在の画面サイズを取得する
${幅} ${高さ} = get window size
# 画面サイズを変更する
set window size 10 10
# 画面サイズを元に戻す
set window size ${幅} ${高さ}
display:noneなボタンをクリックする
<button id="display_none" style="display: none;">見えない</button>
という、display:none
なStyleのボタンがあるとします。
この場合、JavaScriptを使うことで、強引にクリックすることができます。
Example to click on element which is hidden using Execute Javascript? - Google グループ
execute javascript document.getElementById('display_none').click();
Assign Id To Elementを使う
<button id="run_reload" class="reload_element">リロード</button>
というHTMLがあり、このボタンを押すと
var reload = document.getElementById('run_reload');
reload.onclick = function () {
location.reload();
};
と、リロードするJavaScriptがあるとします。
この場合、Assign Id To Element
を使って
- リロード前にタグを設定
- リロード後にタグが存在しないことを確認
を行います。
Assign Id To Element
で設定したidはリロードすると消えてしまう特性を利用します。
Assign Id To Element | Selenium2Library
# id="run_reload"をid="not_reload"に付け替える
assign id to element run_reload not_reload
Assign Id To Elementの注意点
assign id to element id=reload_dummy not_reload
と、locatorにidを指定すると、
Keyword 'Selenium2Library.Assign Id To Element' got positional argument after named arguments.
というエラーになります。
一方、locatorがclassやxpathであればエラーは出ません。
assign id to element class=reload_element not_reload
どうしてもlocatorにidを指定したい場合は、id=
を省略すると、デフォルトの挙動であるid
かname
で検索してくれます。
assign id to element run_reload not_reload
また、Assign Id To Elementはidを付け替えるため、
<button id="run_reload" class="reload_element">リロード</button>
というHTMLの場合、
# idの割り当て
assign id to element run_reload not_reload
# not_reload なidは存在する
page should contain element id=not_reload
# run_reload なidが存在しない
page should not contain element id=run_reload
という挙動となります。
id
の付け替えが困る場合には、idがないElementなど、他の適当なElementを指定します。
alertのOKボタンを押す
<button id="show_alert">警告</button>
というHTMLに対し、
var show_alert = document.getElementById('show_alert');
show_alert.onclick = function () {
alert('OKのみです');
};
とOKのみのalertを表示するJavaScriptがあるとします。
この場合、Dismiss Alert
を使い、alertのOKボタンを押します。
Dismiss Alert | Selenium2Library
# alertを表示する
click element id=show_alert
# alertでOKを押す
dismiss alert
alertのメッセージを取得してOKを押す
同じく、
<button id="show_alert">警告</button>
というHTMLに対し、
var show_alert = document.getElementById('show_alert');
show_alert.onclick = function () {
alert('OKのみです');
};
というJavaScriptがあった場合、メッセージの内容を取得してからOKを押したいとします。
この場合、Get Alert Message
を使い、alertのメッセージを取得します。
Get Alert Message | Selenium2Library
# alertを表示する
click element id=show_alert
# alertのメッセージを取得する
${アラートメッセージ} = get alert message
# alertのメッセージを確認する
should be equal ${アラートメッセージ} OKのみです
alertが表示されていることを確認してからOKを押す
同じく、
<button id="show_alert">警告</button>
というHTMLに対し、
var show_alert = document.getElementById('show_alert');
show_alert.onclick = function () {
alert('OKのみです');
};
というJavaScriptがあった場合、alertが表示されていることを確認してからOKを押したいとします。
この場合、Alert Should Be Present
を使い、alertが表示されていることを確認してからOKを押します。
Alert Should Be Present | Selenium2Library
# alertを表示する
click element id=show_alert
# alertが表示されていることを確認してからOKを押す
alert should be present
alertの表示とメッセージの一致を確認してからOKを押す
同じく、
<button id="show_alert">警告</button>
というHTMLに対し、
var show_alert = document.getElementById('show_alert');
show_alert.onclick = function () {
alert('OKのみです');
};
というJavaScriptがあった場合、alertが表示され、メッセージも一致していることを確認してからOKを押したいとします。
この場合、Alert Should Be Present
で引数を使い、alert表示とメッセージ一致の確認後にOKを押します。
Alert Should Be Present | Selenium2Library
# alertを表示する
click element id=show_alert
# alertが表示され、メッセージも一致していることを確認してからOKを押す
alert should be present OKのみです
alertの表示に時間がかかった場合でもOKを押す
<button id="wait_alert">2秒後に警告</button>
というHTMLに対し、
var wait_alert = document.getElementById('wait_alert');
wait_alert.onclick = function () {
setTimeout(function(){
alert('2秒後のアラート');
}, 2000);
};
と、2秒後にalertを表示するJavaScriptがあるとします。
この場合、Wait Until Keyword Succeeds
とalertを処理するキーワードを併用します。
Wait Until Keyword Succeeds | BuiltIn
Wait Until Keyword Succeeds
の引数は
- 第一引数は、リトライ時間
- 第二引数は、リトライ間隔
- 第三引数は、実行するキーワード
です。
# 5秒の間、1秒ごとに、「Get Alert Message」キーワードを実行する
${アラートメッセージ} = wait until keyword succeeds 5 sec 1 sec get alert message
# alertに「2秒後のアラート」というメッセージがあったことを確認
should be equal ${アラートメッセージ} 2秒後のアラート
confirmのOKを押す
<button id="show_confirm">確認</button>
というHTMLに対し、
var show_confirm = document.getElementById('show_confirm');
show_confirm.onclick = function () {
var answer = confirm('OKとキャンセルです');
if (answer){
alert('OKが押されました');
}
else{
alert('キャンセルされました');
}
};
と、ボタンを押したらconfirmが表示されるJavaScriptがあるとします。
この場合、Confirm Action
を使い、confirmでOKを押します。
Confirm Action | Selenium2Library
ちなみに、Confirm Action
のデフォルトではOKを押します。そのため、デフォルトを変更しない限り、Choose Ok On Next Confirmation
は不要です。
Choose Ok On Next Confirmation | Selenium2Library
# OKボタンを押して、confirmのメッセージを取得する
${確認メッセージ} = confirm action
# confirmのメッセージを確認する
should be equal ${確認メッセージ} OKとキャンセルです
# OKを押した時にalertが表示され、「OKが押されました」というメッセージがあるかを確認する
${アラートメッセージ} = get alert message
should be equal ${アラートメッセージ} OKが押されました
confirmのキャンセルを押す
同じく、
<button id="show_confirm">確認</button>
というHTMLに対し、
var show_confirm = document.getElementById('show_confirm');
show_confirm.onclick = function () {
var answer = confirm('OKとキャンセルです');
if (answer){
alert('OKが押されました');
}
else{
alert('キャンセルされました');
}
};
と、ボタンを押したらconfirmが表示されるJavaScriptがあるとします。
この場合、Choose Cancel On Next Confirmation
とConfirm Action
を使い、confirmでキャンセルを押します。
# 次の確認処理ではキャンセルボタンを押す
choose cancel on next confirmation
# confirmが表示され、キャンセルを押す
${確認メッセージ} = confirm action
should be equal ${確認メッセージ} OKとキャンセルです
# キャンセルを押した時にalertが表示され、「キャンセルされました」というメッセージがあるかを確認する
${アラートメッセージ} = get alert message
should be equal ${アラートメッセージ} キャンセルされました
<button id="show_prompt">入力</button>
というHTMLに対し、
var show_prompt = document.getElementById('show_prompt');
show_prompt.onclick = function () {
var input_message = prompt('値を入力します');
alert(input_message);
};
と、JavaScriptのpromptが表示されるとします。
この場合、Input Text Into Prompt
を使い、promptに入力します。
Input Text Into Prompt | Selenium2Library
また、Input Text Into Prompt
はpromptに入力するだけなので、Confirm Action
によりOKボタンを押します。
なお、ここまでの処理でChoose Cancel On Next Confirmation
が使われていた場合、Confirm Action
してもキャンセルボタンが押されてしまうため、promptへの入力が成功しません。
そのため、Choose Cancel On Next Confirmation
が使われている可能性がある場合は、明示的にChoose Ok On Next Confirmation
を実行した後にConfirm Action
を実行するとよいでしょう。
# promptを表示する
click element id=show_prompt
# ここまででChoose Cancel On Next Confirmationが使われている可能性があるため、
# 明示的にChoose Ok On Next Confirmationを実行し、promptでOKを押すように指定する
choose ok on next confirmation
# promptに入力する
input text into prompt プロンプトに入力しました
# OKボタンを押す
confirm action
# alertではpromptに入力した値が表示されているはずなので、一致しているかを確認する
${アラートメッセージ} = get alert message
should be equal ${アラートメッセージ} プロンプトに入力しました
Headlessブラウザの制限
Headless Chrome v60やPhantomJSの場合、alertやpopup(acceptPopup, cancelPopup)などが未サポートです。
How to run Headless Chrome in Codeception - Codeception / Cookbook - PHP Test Club
そのため、stackoverflowにあるようにモンキーパッチすれば良いかもしれません。
selenium webdriver - chromedriver headless alerts - Stack Overflow
なお、Capybaraでは対応策があるようです。
RSpec + Capybaraでアラート/確認ダイアログを操作する場合は page.driver.browser.switch_to.alert.accept じゃなくて page.accept_confirm を使おう - Qiita
もっとも、Headless Chromeの今後のバージョンでは実装されるかもしれないため、今回はこの部分の対応方法は省略します。
GitHubに上げました。tests/
の中にあるselenium_js_test.robot
ファイルが今回のテストファイルです。
thinkAmi-sandbox/RobotFramework-sample