← Blog

"Selenium Series #15: Selenium Grid — Parallel Execution Across Multiple Machines"

Scale from 4 parallel tests to 40 using Selenium Grid. Set up Hub and Node architecture, run tests on remote machines, integrate with Docker Grid, and connect to cloud platforms.

reading now
views
comments

Series Navigation

Part 14: Cross-Browser Testing

Part 16: CI/CD Integration — Jenkins and Maven Surefire


Why Selenium Grid?

Running 4 parallel tests on one machine is limited by your CPU. Selenium Grid distributes tests across multiple machines:

Without Grid:
Machine 1: [Test1] [Test2] [Test3] [Test4]  ← limited by CPUs

With Grid:
Hub (coordinator)
├── Node 1 (Windows): [Test1] [Test5] [Test9]
├── Node 2 (Linux):   [Test2] [Test6] [Test10]
├── Node 3 (macOS):   [Test3] [Test7] [Test11]
└── Node 4 (Linux):   [Test4] [Test8] [Test12]

Selenium Grid 3 — Hub and Node

Start the Hub

# Download selenium-server-standalone-3.141.59.jar
java -jar selenium-server-standalone-3.141.59.jar -role hub -port 4444

Hub is now running at http://hub-machine:4444/grid/console

Start Nodes

# On each node machine:
java -jar selenium-server-standalone-3.141.59.jar \
  -role node \
  -hub http://hub-machine:4444/grid/register \
  -port 5555 \
  -maxSession 5 \
  -browser "browserName=chrome,maxInstances=5" \
  -browser "browserName=firefox,maxInstances=3"

Connect Tests to Grid

// Replace local driver creation with RemoteWebDriver
DesiredCapabilities caps = new DesiredCapabilities();
caps.setBrowserName("chrome");
caps.setPlatform(Platform.LINUX);

WebDriver driver = new RemoteWebDriver(
    new URL("http://hub-machine:4444/wd/hub"),
    caps
);

Selenium Grid 4 — Standalone and Distributed

Selenium 4 (released 2021) revamped Grid with a new architecture:

Standalone Mode (single machine)

# Download selenium-server-4.x.x.jar
java -jar selenium-server-4.1.0.jar standalone --port 4444

# Tests connect the same way
WebDriver driver = new RemoteWebDriver(
    new URL("http://localhost:4444"),
    new ChromeOptions()
);

Distributed Mode

# Start Event Bus
java -jar selenium-server.jar event-bus --port 4442 --publish-events tcp://*:4442 --subscribe-events tcp://*:4443

# Start Session Map
java -jar selenium-server.jar sessions --session-map redis://localhost:6379

# Start Router
java -jar selenium-server.jar router --hub http://localhost:4444 --sessions http://localhost:5556 --distributor http://localhost:5553

# Start Node
java -jar selenium-server.jar node --hub http://localhost:4444

Docker Selenium Grid

The simplest Grid setup uses Docker Compose:

# docker-compose.yml
version: "3"
services:

  selenium-hub:
    image: selenium/hub:4.1.0
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

  chrome-node:
    image: selenium/node-chrome:4.1.0
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=3
    volumes:
      - /dev/shm:/dev/shm

  firefox-node:
    image: selenium/node-firefox:4.1.0
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

  edge-node:
    image: selenium/node-edge:4.1.0
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
# Start the Grid
docker-compose up -d

# Scale nodes on demand
docker-compose up -d --scale chrome-node=5

# Check Grid status
open http://localhost:4444/grid/console

# Run tests
mvn test -Dgrid.url=http://localhost:4444

# Tear down
docker-compose down

Grid-Aware BaseTest

@BeforeMethod
@Parameters({"browser", "gridUrl"})
public void setUp(
    @Optional("chrome") String browser,
    @Optional("") String gridUrl
) throws MalformedURLException {

    WebDriver driver;

    if (!gridUrl.isEmpty()) {
        // Run on Grid
        ChromeOptions opts = new ChromeOptions();
        opts.addArguments("--no-sandbox", "--disable-dev-shm-usage");

        driver = new RemoteWebDriver(new URL(gridUrl), opts);
        System.out.println("Using Grid: " + gridUrl);
    } else {
        // Run locally
        driver = DriverFactory.createDriver(browser, false);
        System.out.println("Using local: " + browser);
    }

    driverThreadLocal.set(driver);
}
# Local
mvn test

# Grid
mvn test -DgridUrl=http://selenium-hub:4444

What's Next

In Part 16 we integrate our full test suite into Jenkins — configuring Maven builds, running tests on every commit, publishing HTML reports, and sending email notifications on failure.

Discussion

Loading...

Leave a Comment

All comments are reviewed before appearing. No links please.

0 / 1000