Selenideを試した

先日参加した JJUG CCC 2016 FALL で、うらがみさんがSelenideの発表をしていた。

これを拝聴して便利に感じたので試してみた。

スライドはこちら。
Try Selenide

Selenideとは?

SelenideはSelenum WebDriverをラップしたブラウザテストの自動化フレームワークのこと。
Selenum WebDriverは各種ブラウザのWebDriver APIを呼び出す、これも自動化フレームワーク
WebDriverW3C規格なのでプロプラではなくオープンなAPIと言える。

テスト対象のアプリからSelenum WebDriverをラップしたSelenideを呼び出し、Selenum WebDriverは各種ブラウザごとのWebDriverを呼び出すことで、ブラウザからテスト対象のアプリを実行する、というのが全体の流れ。
f:id:nave_kazu:20161207152321p:plain

各種ブラウザのWebDriverを準備する

Selenide/Selenum WebDriverを使うには、まずテスト対象の各種ブラウザのWebDriverを仕込まないとならない。

Selenum WebDriverのサイトに各種ブラウザのWebDriverダウンロード先が記載してあるので、そこから目的のブラウザのWebDriverをダウンロードする。
Selenum WebDriver - Third Party Browser Drivers

ChromeならGoogle Chrome Driver
FirefoxならMozilla GeckoDriver
Internet ExplorerはSelenumが提供しているらしく、Selenum WebDriver - Downloadsの「The Internet Explorer Driver Server」にある。
EdgeからはMicrosoftが提供しているらしく、MicrosoftのサイトWebDriver - Microsoft Edge Development にある。

ダウンロードしたWebDriverは展開して適当なフォルダに保存する。
今回試したのは32bit Windows環境なので、上のサイトから32bit Windows用のChromeFirefoxInternet ExplorerのWebDriverをダウンロードして「C:\SeleniumDriver」に保存した。

ビルドスクリプトの準備と依存関係の追加

ビルドスクリプトを用意し、Selenideを含む関連するライブラリを依存関係に記述する。
関連するライブラリは、Selenide内で使用しているSLF4Jの実装と、単体テストスイートとしてJUnitになる。

Mavenのpom.xmlは下記の通り。

<dependencies>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.21</version>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>com.codeborne</groupId>
    <artifactId>selenide</artifactId>
    <version>4.0</version>
    <scope>test</scope>
  </dependency>
</dependencies>

Gradleのbuild.gradleは下記の通り。

dependencies {
  compile "org.slf4j:slf4j-simple:1.7.21"
  testCompile "junit:junit:4.12"
  testCompile "com.codeborne:selenide:4.0"
}

テストクラスの用意とSelenide/Selenum WebDriverの設定

まずJUnitから呼ばれるテストクラスを用意し、テストクラスの初期化メソッドを定義する。

public class AppTest {
    @BeforeClass
    public static void beforeClass() throws Exception {
    }
}

続いて初期化メソッドにSelenideとSelenum WebDriverの設定をする。

    @BeforeClass
    public static void beforeClass() throws Exception {
        // WebDriverのパスを設定
        System.setProperty("webdriver.ie.driver", "C:\\SeleniumDriver\\IEDriverServer.exe");
        System.setProperty("webdriver.gecko.driver", "C:\\SeleniumDriver\\geckodriver.exe");
        System.setProperty("webdriver.chrome.driver", "C:\\SeleniumDriver\\chromedriver.exe");

        // テスト結果の出力先
        Configuration.reportsFolder = "test-result/reports";

        // 使用するブラウザの指定
//        Configuration.browser = WebDriverRunner.INTERNET_EXPLORER;
//        Configuration.browser = WebDriverRunner.FIREFOX;
        Configuration.browser = WebDriverRunner.CHROME;
    }

System.setProperty()で、ダウンロードしたInternet ExplorerFirefoxChromeのWebDriverのパスを設定する。

Configuration.reportsFolderで、テスト結果(スクリーンショットなど)の保存先を指定する。
今回は相対パスで指定しているので、テスト実行時のカレントフォルダにConfiguration.reportsFolderで指定したフォルダが作成される。

Configuration.browserで、テストするブラウザを指定する。WebDriverRunner.CHROMEを指定しているので、テストを実行すると、chromedriver.exeを経由してChromeブラウザが立ち上がってテストが行われる。
Internet Explorerでテストする場合はWebDriverRunner.INTERNET_EXPLORERを指定して、Firefoxでテストする場合はWebDriverRunner.FIREFOXを指定する。
(うらがみさんは使用するブラウザを実行時引数で指定していたので、その方法はうらがみさんのスライドを参照)

テストメソッドの用意

今回は以下の手順のテストを行う。

  • http://www.yahoo.co.jp/にアクセスする
  • 検索ワードに「selenide」を入力する
  • 検索を実行する
  • 「selenide」の検索結果が出力されているか検証する

最後にスクリーンショットを保存する。

まずはテストクラスにテストメソッドを用意する。

    @Test
    public void selenideTest() throws Exception {
    }

テスト対象のメソッドに@Testを付ける。

http://www.yahoo.co.jp/にアクセスする処理を記述する。

    @Test
    public void selenideTest() throws Exception {
        open("http://www.yahoo.co.jp/");
    }

staticインポートしたopen()メソッドにアクセスするURLを指定する。

次に、検索ワードに「selenide」を入力する処理を記述する。
Yahoo!の検索ワードは下記のHTMLで表現されている。

<input name="p" id="srchtxt" type="text" value="">

なので、セレクタでID「srchtxt」を検索し、そこに値「selenide」を入れる処理を記述することになる。

    @Test
    public void selenideTest() throws Exception {
        open("http://www.yahoo.co.jp/");
        $("#srchtxt").val("selenide");
    }

jQuery風の$メソッドでDOM要素を選択して、val()メソッドで値を入れる。

さらに、検索を実行する処理を記述する。
Yahoo!の検索ボタンは下記のHTMLで表現されている。

</label><input type="submit" id="srchbtn" class="srchbtn" value="検索">

先ほどと同様にセレクタでID「srchbtn」を検索し、クリックを実行するclick()メソッドを呼び出す。

    @Test
    public void selenideTest() throws Exception {
        open("http://www.yahoo.co.jp/");
        $("#srchtxt").val("selenide");
        $("#srchbtn").click();
    }

その後、検索結果のHTMLのbody部に「selenide」の検索結果が出力されているか確認する。

    @Test
    public void selenideTest() throws Exception {
        open("http://www.yahoo.co.jp/");
        $("#srchtxt").val("selenide");
        $("#srchbtn").click();

        $("body").shouldHave(text("Selenide: concise UI tests in Java - このページを和訳"));
    }

最後にスクリーンショットを保存する。

    @Test
    public void selenideTest() throws Exception {
        open("http://www.yahoo.co.jp/");
        $("#srchtxt").val("selenide");
        $("#srchbtn").click();

        $("body").shouldHave(text("Selenide: concise UI tests in Java - このページを和訳"));
        screenshot("selenideTest");
    }

今回は相対パスで指定しているので、テスト実行時のカレントフォルダにConfiguration.reportsFolderで指定したフォルダが作成される。

テストの実行

Mavenで実行する場合、下記を実行する。

mvn test

Gradleで実行する場合、下記を実行する。

gradle test

どちらの場合でも、ブラウザが立ち上がって(今回の場合はChrome)、検索ワード「selenide」を入れて、検索して、検索結果が表示されて、ブラウザが終了してテストが正常終了すると思う。

テスト結果を保存しているはずなので、カレントフォルダの「test-result/reports」を見てみると、「selenideTest.png」と「selenideTest.html」が出来ている。
「selenideTest.png」はスクリーンショットの画像イメージで、「selenideTest.html」はその時のHTML。両方撮ってくれる。

「selenideTest.png」はこんな感じ。
f:id:nave_kazu:20161212113408p:plain

最後に

駆け足に試したが、Selenideいいね。
今後も使うと思う。

うらがみさんのスライドの中では他に、ページオブジェクトパターンやSeleniumが提供しているDockerイメージを使ったテストなども紹介している。
これらも試してみようと思う。