ポップアップウィンドウのスクリーンショットを撮影する
WebアプリケーションをSeleniumでテストする際に良くある疑問に『ポップアップウィンドウを表示して○○する操作があるけれど、どうやってテストするの?』があります。今回はSeleniumでポップアップウィンドウを扱う方法について解説します。
ポップアップウィンドウのテスト
Seleniumの操作対象を切り替える
Selenium WebDriverはWindowやFrameに対して操作を行うことができます。操作を行うには該当のWindowやFrameをWebDriverのターゲットとして指定します。WebDriverの switchTo メソッドはWebDriverのターゲットを変更するためのメソッドで、次の様に使用します。
// 指定するウィンドウ名はJavaScriptの "window.open" 第二引数で指定するWindow名です
WebDriver newDriver = driver.switchTo().window("Windowの名前");
// Frameにターゲットを移動する場合
WebDriver newDriver = driver.switchTo().frame("フレームの名前やWebElementオブジェクト");
// アラート(alert/confirm)にターゲットを移動する場合
Alert alert = driver.switchTo().alert();
alert.accept(); // alertでボタンを押す、confirmでOKを押す
// alert.cancel(); // confirmでcancelを押す
WebDriverが現在対象としているWindowの名前を取得するには getWindowHandle メソッドや getWindowHandles メソッドを使用します。
String mainWindowHandle = driver.getWindowHandle();
// 現在開いているWindow一覧を取得
Set<String> windowHandles = driver.getWindowHandles();
// WebDriverが操作の対象とするWindowを別のWindowに変更
driver.switchTo().window((String) windowHandles.toArray()[i]);
// ...別のWindow操作
// 元のWindowにWebDriverの対象を戻す
driver.switchTo().window(mainWindowHandle);
テストを作ってみる
テストサイトについて
サンプル用に作成したテストサイトに対してPitaliumでスクリーンショットを撮影するコードを書いてみます。今回使用するWebサイトはユーザーがログインできる機能があり、次のような構造になっています。
- メイン画面
メイン画面はユーザーが最初に訪れる画面です。ログイン画面をポップアップウィンドウとして表示するボタンがあります。 - ログイン画面
ログイン画面はユーザーがメールアドレス/パスワードを入力してログインを実行するポップアップウィンドウの画面です。ユーザーがログインを実行するとログイン画面のウィンドウは自動でクローズされ、メイン画面へと戻ります。
コードを書いてみる
1.画面を開く
まずはメイン画面を開き、スクリーンショットを撮影します。
ログインするためのボタンがあることが確認できます。
driver.get("popupWindow");
// スクリーンショット撮影
assertionView.assertView("OpenMainWindow");
2.ボタンをクリックしてログイン画面を開く
ログインボタンをクリックし、ログインウィンドウを開きます。
3.WebDriverの対象Windowを変更
WebDriverの対象Windowをログイン画面に設定します。
サンプルサイトでは新しいウィンドウを以下のように作成しています。
ログイン画面のウィンドウ名は”login”ですので、 switchTo().window()に "login" を指定します。
また、最後に元の画面に戻る操作を行いたいので、最初に開いた画面のWindowHandleを取得しておきます。
String mainWindow = driver.getWindowHandle();
// 新しく開いたポップアップウィンドウにWebDriverの対象を移動
driver.switchTo().window("login");
###
ポップアップウィンドウを開く方法として、 showModalDialog を利用することがあります。
showModalDialogを対象としたテスト方法は 8.showModalDialogでウィンドウを開く場合 を参照下さい。
4.ログイン画面のスクリーンショットを取得
実際にログイン画面にWebDriverの対象が移動していることを確認するため、スクリーンショットを取得します。
メールアドレス/パスワード入力欄とログイン実行ボタンがあることが分かります。
5.ログイン情報を入力
ログイン動作を行うため、メールアドレスとパスワードを入力します。
入力した状態をチェックするためにスクリーンショットも取得します。
driver.findElementById("email").sendKeys("pitalium.sample@localhost.com");
driver.findElementById("password").sendKeys("password");
// スクリーンショット撮影
assertionView.assertView("EnterLoginParams");
6.メイン画面へ戻る
ログイン画面でログインボタンをクリックし、ログイン処理を実行します。
switchTo().window() のターゲットに手順3で取得したメインウィンドウの名前を設定し、メイン画面へ戻ります。
最後に、ログイン処理が完了したことを確認するため、スクリーンショットを撮影します。
driver.findElementById("login").click();
// 先に取得した元の画面を driver.switchTo に指定
driver.switchTo().window(mainWindow);
// スクリーンショット撮影
assertionView.assertView("LoggedIn");
7.テストコード全体
手順1~6までをまとめた全体のテストコードです。
@Test
public void popupWindowTest() throws Exception {
// 1.メイン画面を開き、全体のスクリーンショットを撮影します。
driver.get("popupWindow");
assertionView.assertView("OpenMainWindow");
// 2.ボタンをクリックして子画面を開きます。
driver.findElementById("login").click();
// 3.WebDriverの対象Windowを子画面に設定します。
// switchTo().window()に渡すWindow名は、JavaScriptでwindow.openをコールした時の第二引数です。
String mainWindow = driver.getWindowHandle();
driver.switchTo().window("login");
// 4.移動先のWindowでスクリーンショットを撮影します。
assertionView.assertView("OpenLoginWindow");
// 5.ログイン情報を入力してスクリーンショットを撮影します。
driver.findElementById("email").sendKeys("pitalium.sample@localhost.com");
driver.findElementById("password").sendKeys("password");
assertionView.assertView("EnterLoginParams");
// 6.ログインボタンをクリックし、WebDriverの対象Windowを元の画面へと戻します。
// 移動後スクリーンショットを撮影します。
driver.findElementById("login").click();
driver.switchTo().window(mainWindow);
assertionView.assertView("LoggedIn");
}
}
8.showModalDialogでウィンドウを開く場合
window.showModalDialogを使用する場合、window.openの場合と異なりウィンドウの名前を指定することが出来ません。そのため、showModalDialogで開いたウィンドウを指定するには WebDriver#getWindowHandles でウィンドウの一覧を取得し、現在開いているウィンドウではないWindowHandleを指定する必要があります。
String mainWindow = driver.getWindowHandle();
// WindowHandle一覧を取得
Set<String> windowHandles = driver.getWindowHandles();
if (windowHandles.size() != 2) {
fail("Windowが開かれていない、または複数のポップアップが表示されている");
return;
}
// 現在開いているウィンドウでは無いWindowHandleを探し、driver.switchToに指定する
for (String windowHandle : windowHandles) {
if (!windowHandle.equals(mainWindow)) {
driver.switchTo().window(windowHandle);
}
}
showModalDialogテストの注意点
- 上記テストコードはIE11で動作を確認しています。
- Firefox 42では上記テストコードは動作しません。
showModalDialogは非推奨に指定されているため、showModalDialogとFirefoxを組み合わせたテストを実行しないで下さい。 - Chrome 47では上記テストコードは動作しません。
Chrome 37以上のバージョンでshowModalDialogは削除されているため、使用することができません。
ソースコード
このサンプルのソースコードはGithubレポジトリの次のパスを参照ください。
(showModalDialogの場合)