Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

selenium-jupiterを試した

JUnit 5にTemporalyFolderに相当する機能がなかったため、自分のプロジェクトでは長らくJUnit4を使っていました。しかし5.4でTempDirが来たため、徐々にJUnit5に置き換えています。

その過程でSelenideを使った統合テストをJUnit5に置き換えたのですが、selenium-jupiterがなかなか便利でした。作業したリポジトリこちらです。 ただ一筋縄に行かない部分もあるので、備忘録を残します:

SpringBootTestとSelenideとの噛みあわせ

SpringBootTestにはランダムなポートでアプリケーションサーバを起動する機能がありテストの並列実行に役立ちます。 またselenium-jupiterはSelenideをサポートしており、テストメソッドのパラメータに SelenideDriver を指定するとインスタンスを作って注入してくれます。

さてSelenideにはbaseUrlという設定がありConfiguration.baseUrlにURL文字列を指定しておくとSelenideDriverインスタンス作成時に使ってくれます。 これによりテストメソッドではスキーマドメイン名、ポート番号などを省略した相対URLを指定するだけで済むのですが。SelenideDriverインスタンス@BeforeEachメソッドが実行されたタイミングで既に作成されているので以下のようにbaseUrlを指定しても効いてくれません。

@LocalServerPort
private int port;

@BeforeEach
void config() {
  Configuration.baseUrl = String.format("http://localhost:%d/", port);
}

@Test
void test(SelenideDriver driver) {
  System.out.println(driver.config().baseUrl()); // デフォルトの http://localhost:8080/ になってしまう
}

現状きれいに解決する方法が見当たらないので、テストメソッドでは相対URLではなく絶対URLを使うようにしています。

SpringBootTestするならDocker内ブラウザは使わないほうが良い

selenium-jupiterではDocker内のブラウザを使うこともできるのですが、ドキュメント末尾に注意書きがあるようにローカルにアプリケーションサーバを建てているときは一筋縄では行きません。DockerコンテナからDockerホスト(localhost)にHTTP接続をする必要があるのですが、ホスト名を解決する統一的な手法が存在しないのです。特にLinux環境ではホスト名ではなくIPアドレスを取得する必要があり、一度 ip addr show docker0|grep 'inet '|awk '{$1=$1};1'|cut -d ' ' -f 2|cut -d / -f 1 などの操作をしてシステムプロパティ経由でテストに対して渡す必要があり面倒です。baseUrlが使えればホスト名構築処理を抽象クラスで集中管理できたのでまだマシだったのでしょうが……。

他にもブラウザで何らかの問題が起こったときのトラブルシュートが面倒ということもあり、SpringBootTestを使う場合はDocker内ブラウザは使用しないほうが良いのではと感じました。Travis CIなら安定版のChromeをCI環境にインストールする方法があるので、コンテナを使う必要性もあまりありません。