kagamihogeの日記

kagamihogeの日記です。

Selenium Gridをdockerで使う

Selenium Gridをdockerコンテナでリモートブラウザを起動するやり方で使用する。

ソースコードと手順

docker-compose.yml

DockerでSelenium Gridを構築してクロスブラウザテストを自動化するを参考にdocker-compose.ymlを作成する。

version: '3.8'

services:
  selenium-hub:
    image: selenium/hub:4.7.2
    ports:
      - 4444:4444
      - 4442:4442
      - 4443:4443

  node-chrome:
    image: selenium/node-chrome:4.7.2
    depends_on:
      - selenium-hub
    environment:
      - TZ=Asia/Tokyo
      - HUB_HOST=selenium-hub
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

  node-firefox:
    image: selenium/node-firefox:4.7.2
    depends_on:
      - selenium-hub
    environment:
      - TZ=Asia/Tokyo
      - HUB_HOST=selenium-hub
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
docker-compose up

で起動して http://localhost:4444/ui で下記キャプチャのようなコンソールが開けばOK.

java

javaseleniumのコードを書く。

plugins {
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.seleniumhq.selenium:selenium-java:4.7.2'
}

https://transit.yahoo.co.jp/ にアクセスしてtitle出力するだけのサンプルコード。

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;

import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class RemoteSeleniumSample {

  public static void main(String[] args) throws MalformedURLException {
    URL address = new URL("http://localhost:4444");
    ChromeOptions chromeOption = new ChromeOptions();
    chromeOption.setHeadless(true);
    chromeOption.addArguments("--disable-gpu", "--disable-dev-shm-usage");

    RemoteWebDriver driver = new RemoteWebDriver(address, chromeOption);
    try {
      driver.get("https://transit.yahoo.co.jp/");
      WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
      wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.name("from")));
      System.out.println(driver.getTitle());
    } finally {
      driver.quit();
    }
  }
}

複数コンテナ起動

設定で複数ブラウザセッションを起動出来るし、複数コンテナ起動して並列実行も出来る。

 docker-compose up --scale node-chrome=3

javaから3スレッドでseleinumを起動する。

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class RemoteSeleniumSample2 {

  public static void main(String[] args) throws MalformedURLException, InterruptedException, ExecutionException {
    ExecutorService es = Executors.newFixedThreadPool(3);
    Future<?> f1 = es.submit(() -> execute());
    Future<?> f2 = es.submit(() -> execute());
    Future<?> f3 = es.submit(() -> execute());

    f1.get();
    f2.get();
    f3.get();

    es.shutdown();
  }

  static void execute() {
    RemoteWebDriver driver = null;
    try {
      URL address = new URL("http://localhost:4444");

      ChromeOptions chromeOption = new ChromeOptions();
      chromeOption.setHeadless(true);
      chromeOption.addArguments("--disable-gpu", "--disable-dev-shm-usage");

      driver = new RemoteWebDriver(address, chromeOption);
      WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

      driver.get("https://transit.yahoo.co.jp/");
      wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.name("from")));

      System.out.println(driver.getTitle());
    } catch (MalformedURLException e) {
      e.printStackTrace();
    } finally {
      driver.quit();
    }
  }

}

コンソール画面は下記のように3個のchromeブラウザ用インスタンスが作成される。また、実行中かどうかも分かる。

ハマった点

unknown error: session deleted because of page crash from tab crashed

メモリ省力化設定を入れて「Selenium::WebDriver::Error::UnknownError: unknown error: session deleted because of page crash」が出ないようにする に従って各種オプションを設定する。