2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

HTMLの要素を調べてPageクラス(Selenide利用)を作成する

2
Last updated at Posted at 2018-04-20

はじめに

Selenium(Java)でE2Eテスト環境を構築する

構築をしたものの、『Pageクラス作るのかよー』とか言われて重い腰を上げてもらえそうなので、できるだけ簡単にPageクラスを作る方法を記録しておきます。
今までの経験上たぶん色々言ってくる:innocent:

操作をしたい要素を特定する(CSSセレクタなど)

Windows版で解説。
Chromeのデベロッパーツールを使用します。

  1. 調べたい画面を表示
    aWS050241.JPG

  2. F12キーでデベロッパーツールを表示
    aWS050242.JPG

  3. 選択ボタンをクリックし、操作したい要素を選択
    aWS050243.JPG

  4. 反転されたHTMLソースを右クリックし、Copy - Copy selector で『#q』のような情報がコピーできる
    aWS050244.JPG

Pageクラスを作成してみる

先ほど調べた要素を反映させると以下のPageクラスを作成することになる

Google.java
package page;

import static com.codeborne.selenide.Selenide.*;

import org.openqa.selenium.WebDriver;

public class Google extends PageBase {

    public static final String _url = "https://www.google.co.jp/webhp";

    public Google(WebDriver webDriver) {
        super(webDriver);
    }

    private String _id_search = "#lst-ib";

    // ****************************************
    // 検索ページ
    // ****************************************

    public Google __検索ワード入力(String s) {
        $(_id_search).setValue(s);
        return this;
    }

    public Google __検索を行う() {
        $(_id_search).submit();
        return this;
    }
}

テストは以下のようなコード。

GoogleTest.java
package test;

import org.junit.Test;

import com.htmlhifive.pitalium.core.model.ScreenshotArgument;

import page.Google;

public class GoogleTest extends TestBase {

    @Test
    public void OK() throws Exception {

        driver.get(Google._url);
        Google page = new Google(driver);

        page.__検索ワード入力("test")
            .__検索を行う();

        ScreenshotArgument arg = ScreenshotArgument.builder("result").addNewTarget().build();
        assertionView.verifyView(arg);
    }
}

クリックメニューを扱えるようなPageクラスを作成してみる

検索結果表示後のツールをクリックして操作できるメソッドを追加してみる。
要素の調べ方は先ほどと同じ。

Seleniumは操作が早すぎるようで、要素がないみたいなエラーになることがある。
クリック後に表示される要素を待つようにすると安定する。

Google.java
package page;

import static com.codeborne.selenide.Condition.*;
import static com.codeborne.selenide.Selenide.*;

import java.util.Iterator;

import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;

import com.codeborne.selenide.SelenideElement;

public class Google extends PageBase {

    public static final String _url = "https://www.google.co.jp/webhp";

    public Google(WebDriver webDriver) {
        super(webDriver);
    }

    private String _id_search = "#lst-ib";

    // ****************************************
    // 検索ページ
    // ****************************************

    public Google __検索ワード入力(String s) {
        $(_id_search).setValue(s);
        return this;
    }

    public Google __検索を行う() {
        $(_id_search).submit();
        return this;
    }

    // ****************************************
    // 検索結果ページ(以下は本来なら別クラス)
    // 本来なら「__検索を行う()」メソッドで検索結果Pageクラスを返せば良い
    // ****************************************

    public Google __ツールをクリック() {
        $("#hdtb-tls").click();
        return this;
    }

    public Google __ツール$期間をクリック() {
        // ツール選択後のメニューが表示されているか確認
        if (!$("#hdtbMenus").isDisplayed()) {
            __ツールをクリック();
        }
        // 選択後に表示される項目を60秒待つ
        $("#hdtbMenus").waitUntil(appear, 60000);

        $("#hdtbMenus > div > div:nth-child(5) > div").click();

        return this;
    }

    public Google __ツール$期間$1時間以内をクリック() {
        return __ツール$期間$指定文字をクリック("1 時間以内");
    }

    public Google __ツール$期間$1年以内をクリック() {
        return __ツール$期間$指定文字をクリック("1 年以内");
    }

    private Google __ツール$期間$指定文字をクリック(String text) {
        // 期間のメニューが表示されているか確認
        if (!$("#hdtbMenus > div > ul.hdtbU.hdtb-mn-o").isDisplayed()) {
            __ツール$期間をクリック();
        }
        // 選択後に表示される項目を60秒待つ
        $("#hdtbMenus > div > ul.hdtbU.hdtb-mn-o").waitUntil(appear, 60000);

        return matchTextClick(text, $$("#hdtbMenus > div > ul.hdtbU.hdtb-mn-o > li").iterator());
    }

    private Google matchTextClick(String text, Iterator<SelenideElement> seItr) {

        boolean ckickFlg = false;

        while (seItr.hasNext()) {
            SelenideElement se = seItr.next();
            if (text.equals(se.getText())) {
                se.click();
                ckickFlg = true;
                break;
            }
        }

        if (!ckickFlg) {
            throw new NoSuchElementException("Click error:" + text);
        }

        return this;
    }
}

テストは以下のようなコード。

GoogleTest.java
package test;

import org.junit.Test;

import com.htmlhifive.pitalium.core.model.ScreenshotArgument;

import page.Google;

public class GoogleTest extends TestBase {

    @Test
    public void OK() throws Exception {

        driver.get(Google._url);
        Google page = new Google(driver);

        page.__検索ワード入力("test")
            .__検索を行う();

        ScreenshotArgument arg = ScreenshotArgument.builder("result1").addNewTarget().build();
        assertionView.verifyView(arg);

        page.__ツール$期間$1時間以内をクリック();
// 画面状態が完璧にわかるなら以下の記述の方が処理速度が速い
//        page.__ツールをクリック()
//            .__ツール$期間をクリック()
//            .__ツール$期間$1時間以内をクリック();


        arg = ScreenshotArgument.builder("result2").addNewTarget().build();
        assertionView.verifyView(arg);

        page.__ツール$期間$1年以内をクリック();


        arg = ScreenshotArgument.builder("result3").addNewTarget().build();
        assertionView.verifyView(arg);
    }
}

Frameが分かれている画面を処理するPageクラスを作ってみる

Frameが分かれているページは切り替えなくてはいけないらしい。
この制御もやはりPageクラスでカバーする方が良いと思ってる。
(切り替えなしでいける方法があればご教授ください)

18/04/23 変更
コメントをいただいた内容は理解できたが、実力不足でコードには反映できず:scream:
"__項目1に入力"メソッドでも同じような記述ができれば良いのだが思いつかず。

FrameSample.java
package page;

import static com.codeborne.selenide.Selenide.*;

import org.openqa.selenium.WebDriver;

import com.codeborne.selenide.SelenideElement;
import com.codeborne.selenide.WebDriverRunner;

public class FrameSample extends PageBase {

    public static final String _url = "https://";

    public FrameSample(WebDriver webDriver) {
        super(webDriver);
    }

    /** デフォルトフレームに存在している要素に入力 */
    public FrameSample __項目1に入力(String s) throws InterruptedException {
        $("#in1").setValue(s);
        return this;
    }

    /** 別フレームに存在している要素に入力 */
    public FrameSample __項目2に入力(String s) throws InterruptedException {
        switcFrame($(".iframe"));
        $("#in2").setValue(s);
        switchDefaultFrame();
        return this;
    }

    /***
     * デフォルトフレームに切り替える
     * @throws InterruptedException
     */
    private void switchDefaultFrame() throws InterruptedException{
        // 処理が安定しないのでフレーム変更にWaitをとりあえず入れる
        WebDriverRunner.getWebDriver().switchTo().defaultContent();
        Thread.sleep(2000);
    }

    /***
     * 別フレームに切り替える
     * @param se フレームのElement
     * @throws InterruptedException
     */
    private void switcFrame(SelenideElement se) throws InterruptedException{
        // 処理が安定しないのでフレーム変更にWaitをとりあえず入れる
        WebDriverRunner.getWebDriver().switchTo().frame(se);
        Thread.sleep(2000);
    }
}
2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?