JShellを使ってSeleniumで対話的にブラウザ操作を行う


はじめに

今回はJavaでSeleniumを使う際にJava9で導入された対話環境(いわゆるREPL)のJShellを使ってみようと思います。

なぜREPLか

Selenium WebDriverで自動テストを記述する際、皆さんはDOM要素の取得をどのように行っているでしょうか。大抵の場合、各ブラウザの開発者ツールで対象ページを開き、idのように一意に取得できるものを探しそれをもとにコードに起こしているでしょう。
ですが複雑なDOM構造やidが振られていない場合どうするでしょう。DOM構造からあたりをつけて、それをもとにコードを書き試しに実行し意図通りに取れたかprintfデバックを行って……ということもあるのではないでしょうか。

DOMをたどっていく場合やWebDriverのラッパー固有のAPIを用いる場合、実際に動かしてみないと意図通りに要素取得ができるかまた操作時の振る舞いも意図通りか検証できないことがあります。実行するにしてもテストシナリオの後ろの方にあると、確認するだけでも時間がかかり非常に効率が悪くなってしまいます。

その解決手段の一つとして、言語毎に提供されているREPLのような対話環境を用いるということがあります。REPLでSeleniumを動かしブラウザを起動させ目的の画面までは手動で操作し、コードの確認をREPLで行うというものです。
Javaには最近までREPLがなかったため、代替手段としてIDEのデバッグ機能を使い疑似的に対話環境を使うということを筆者は行ってきました。ですが、Java9からは公式REPLであるJShellが導入されたためこれを使い対話的に操作する方法を解説していきます。

前提条件

この記事で書くことを試すには以下の環境が必要です。

ソフトウェア バージョン等 備考
Oracle JDK 9以上 JShellを動かすため
Apache Maven 3.3.9 jshell-maven-pluginの条件
IntelliJ IDEA 2017.3以降 JShell Consoleのため

なお筆者は以下の環境で検証しました。

ソフトウェア バージョン等
Oracle JDK 10
Apache Maven 3.5.2
IntelliJ IDEA Ultimate 2018.1

その1 IntelliJ IDEAのJShell Consoleを使う

一番簡単なのは、IntelliJ IDEAに内蔵されているJShell Consoleを使う方法です。
IntelliJ IDEAの[Tool]-[JShell Console]を起動させます。以下のような感じです。

起動させると以下のようなエディタが開きます。

ここで入力したあとで「▶」を押下すると評価されます。部分的に評価したい場合はその範囲を選択しておくことで、その範囲のみが対象となります。

動かしてみる

それでは試しに実行してみましょう
https://github.com/shimashima35/codezine-digital-sample をCloneすると、pom.xmlでSelenideの設定がされています。このプロジェクトを開いた以上帯でJShell Consoleを起動し、以下のコードを入力し評価します。

import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.WebDriverRunner;

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

Configuration.browser = WebDriverRunner.FIREFOX;
open("https://www.google.com")

そうすると、Firefox Driverをダウンロード、Firefox起動、Googleへのアクセスが行われそこで止まります。
この状態まで行けばあとはこのJShell Consoleで任意のコードを記述し、そのたびに評価を実行することで対話的にSelenium(この場合はSelenide)を動かすことができます。

その2 jshell-maven-plugin を使う

jshell-maven-pluginとは、JavaコミッターでJShellの開発を行っていた@bitter_foxさんが開発したmaven pluginです。
JShellの起動時にclasspathを設定するのは意外に面倒です。プロジェクト自体がmavenをベースとしているのであれば、このpluginを使うことでpomに記載された設定をもとにJShellを使うことができます。

導入方法

jshell-maven-pluginは、この記事の執筆時点(2018/04/06)でまだCentral Repositoryにあがっていません。そのため、導入にはソースからビルドしてローカルもしくはインハウスリポジトリへのインストールが必要になります。

手順は前述の公式サイトのREADME.mdに記載がある通りで以下のようにJDK9に対してJAVA_HOME環境変数を設定したのちにインストールを実行します。

JAVA_HOME=/path/to/your/jdk9 mvn clean install

これでローカルリポジトリにはいります。

設定

pluginを使うために、pom.xmlへ下記を追加します。

    <build>
        <plugins>
            <plugin>
                <groupId>net.java.openjdk.shinyafox</groupId>
                <artifactId>jshell-maven-plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
            </plugin>
        </plugins>
    </build>

実行

JAVA_HOME\binにコマンドパスが通っていれば以下で起動します。

mvn jshell:compile

実行後以下のように標準出力が行われ待ち状態になります。

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building codezine 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- jshell-maven-plugin:1.0-SNAPSHOT:compile (default-cli) @ codezine ---
[INFO] Starting jshell with [
中略
]
|  JShellへようこそ -- バージョン10
|  概要については、次を入力してください: /help intro

jshell>

これ以降、pom.xml で依存を設定されたjarへのクラスパスが通った状態でjshellが使えます。

終わりに

JavaでもREPLが導入されSeleniumの操作も対話的に行うことができるようになりました。
静的言語としての強みを生かしつつ、REPLを使って効率的に開発を行うことが今まで以上に可能になったのではないでしょうか。
是非みなさんも一度試してみてください。