Selenium Grid 4: Complete Setup Handleiding voor Localhost
Selenium Grid 4 is een krachtige tool voor het parallel uitvoeren van geautomatiseerde tests over meerdere browsers en machines. Deze handleiding toont je hoe je een lokale Selenium Grid opzet, zowel handmatig als met Docker.
Wat is Selenium Grid 4?
Selenium Grid 4 biedt een gedistribueerde test-uitvoering platform dat:
- Parallelle test uitvoering mogelijk maakt over meerdere browsers
- Cross-browser testing ondersteunt (Chrome, Firefox, Safari, Edge)
- Schaalbaarheid biedt voor grote test suites
- Resource optimalisatie mogelijk maakt door tests te verdelen
Nieuwe Features in Grid 4
- Standalone mode voor eenvoudige setup
- Verbeterde monitoring via de Grid Console
- Event bus architectuur voor betere communicatie
- GraphQL support voor programmatische interactie
- Docker support out-of-the-box
Methode 1: Handmatige Setup (Windows/Linux/macOS)
Vereisten
Java 11 of hoger: Controleer je Java versie:
java -version
Selenium Server JAR: Download de laatste versie:
# Download via curl (Linux/macOS)
curl -L "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.17.0/selenium-server-4.17.0.jar" -o selenium-server-4.17.0.jar
# Of download handmatig van: https://selenium-release.storage.googleapis.com/index.html
Stap 1: Selenium Hub Starten
Open een terminal/command prompt en navigeer naar de map met de JAR file:
# Start de Hub
java -jar selenium-server-4.17.0.jar hub
# Met custom configuratie
java -jar selenium-server-4.17.0.jar hub --config hub-config.json
Standaard Hub instellingen:
- Port: 4444
- Console URL: http://localhost:4444/ui
- GraphQL: http://localhost:4444/graphql
Stap 2: Node Registreren
Open een nieuwe terminal en start een node:
# Basis node setup
java -jar selenium-server-4.17.0.jar node --selenium-manager true
# Node met specifieke browsers
java -jar selenium-server-4.17.0.jar node \
--detect-drivers \
--selenium-manager true \
--override-max-sessions true \
--max-sessions 4
Stap 3: Setup Verificatie
1. Grid Console Controleren: Ga naar http://localhost:4444/ui en controleer of:
- Hub status “Ready” toont
- Node(s) geregistreerd zijn
- Beschikbare browsers zichtbaar zijn
2. Test Sessie Starten:
# Test met curl
curl --location 'http://localhost:4444/session' \
--header 'Content-Type: application/json; charset=utf-8' \
--data '{
"capabilities": {
"firstMatch": [
{
"goog:chromeOptions": {
"args": ["--no-sandbox", "--disable-dev-shm-usage"],
"extensions": []
},
"browserName": "chrome"
}
]
}
}'
3. Met Python/Selenium:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# Grid configuratie
grid_url = "http://localhost:4444"
# Chrome capabilities
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
# Connect naar Grid
driver = webdriver.Remote(
command_executor=grid_url,
options=chrome_options
)
# Test uitvoeren
driver.get("https://www.example.com")
print(f"Title: {driver.title}")
driver.quit()
Geavanceerde Handmatige Configuratie
Hub Configuration (hub-config.json):
{
"configs": [
"org.openqa.grid.common.RegistrationRequest",
"org.openqa.grid.web.servlet.console.ConsoleServlet"
],
"host": "0.0.0.0",
"port": 4444,
"cleanUpCycle": 5000,
"timeout": 30000,
"browserTimeout": 60000,
"maxSession": 5,
"newSessionWaitTimeout": -1,
"throwOnCapabilityNotPresent": true
}
Node Configuration (node-config.json):
{
"capabilities": [
{
"browserName": "chrome",
"maxInstances": 3,
"seleniumProtocol": "WebDriver",
"version": "",
"platform": "ANY"
},
{
"browserName": "firefox",
"maxInstances": 2,
"seleniumProtocol": "WebDriver",
"version": "",
"platform": "ANY"
}
],
"configuration": {
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"host": "localhost",
"port": 5555,
"maxSession": 5,
"register": true,
"registerCycle": 5000,
"hubHost": "localhost",
"hubPort": 4444
}
}
Methode 2: Docker Setup (Aanbevolen)
Vereisten
Docker & Docker Compose: Installeer van https://docs.docker.com/get-docker/
# Controleer installatie
docker --version
docker-compose --version
Basic Docker Compose Setup
docker-compose.yml:
version: '3.8'
services:
# Selenium Hub
selenium-hub:
image: selenium/hub:4.17.0
container_name: selenium-hub
ports:
- "4444:4444"
- "4442:4442"
- "4443:4443"
environment:
- GRID_MAX_SESSION=16
- GRID_BROWSER_TIMEOUT=60
- GRID_TIMEOUT=60
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4444/wd/hub/status"]
interval: 30s
timeout: 10s
retries: 3
# Chrome Node
chrome-node:
image: selenium/node-chrome:4.17.0
container_name: chrome-node
depends_on:
selenium-hub:
condition: service_healthy
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_MAX_SESSIONS=4
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
volumes:
- /dev/shm:/dev/shm
ports:
- "5900:5900" # VNC port
# Firefox Node
firefox-node:
image: selenium/node-firefox:4.17.0
container_name: firefox-node
depends_on:
selenium-hub:
condition: service_healthy
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_MAX_SESSIONS=4
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
volumes:
- /dev/shm:/dev/shm
ports:
- "5901:5900" # VNC port
# Edge Node
edge-node:
image: selenium/node-edge:4.17.0
container_name: edge-node
depends_on:
selenium-hub:
condition: service_healthy
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_MAX_SESSIONS=2
volumes:
- /dev/shm:/dev/shm
ports:
- "5902:5900" # VNC port
Grid Starten
# Start alle services
docker-compose up -d
# Logs bekijken
docker-compose logs -f
# Status controleren
docker-compose ps
Scaling & Management
Nodes Schalen:
# Scale Chrome nodes
docker-compose up -d --scale chrome-node=3
# Scale alle node types
docker-compose up -d --scale chrome-node=3 --scale firefox-node=2 --scale edge-node=2
# Handmatig node toevoegen
docker run -d \
--name additional-chrome \
--network selenium-grid_default \
-e SE_EVENT_BUS_HOST=selenium-hub \
-e SE_EVENT_BUS_PUBLISH_PORT=4442 \
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
-v /dev/shm:/dev/shm \
selenium/node-chrome:4.17.0
Grid Stoppen:
# Stop en verwijder containers
docker-compose down
# Stop en verwijder inclusief volumes
docker-compose down -v
# Force cleanup
docker-compose down --remove-orphans
Geavanceerde Docker Configuratie
Met VNC Support voor Visual Debugging
docker-compose-vnc.yml:
version: '3.8'
services:
selenium-hub:
image: selenium/hub:4.17.0
container_name: selenium-hub
ports:
- "4444:4444"
chrome-debug:
image: selenium/node-chrome-debug:4.17.0
container_name: chrome-debug
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- VNC_NO_PASSWORD=1
volumes:
- /dev/shm:/dev/shm
ports:
- "5900:5900" # VNC
- "7900:7900" # noVNC (web interface)
firefox-debug:
image: selenium/node-firefox-debug:4.17.0
container_name: firefox-debug
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- VNC_NO_PASSWORD=1
volumes:
- /dev/shm:/dev/shm
ports:
- "5901:5900" # VNC
- "7901:7900" # noVNC
VNC Toegang:
- Chrome: http://localhost:7900 (no password)
- Firefox: http://localhost:7901 (no password)
- VNC Client: localhost:5900 (Chrome), localhost:5901 (Firefox)
Video Recording Setup
chrome-video:
image: selenium/video:ffmpeg-4.3.1-20230404
container_name: chrome-video
depends_on:
- chrome-node
environment:
- DISPLAY_CONTAINER_NAME=chrome-node
- FILE_NAME=chrome_video.mp4
volumes:
- ./videos:/videos
Test Code Voorbeelden
Python Test Setup
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import threading
import time
class TestSeleniumGrid:
@pytest.fixture(params=["chrome", "firefox", "edge"])
def driver(self, request):
"""Multi-browser test fixture"""
grid_url = "http://localhost:4444"
if request.param == "chrome":
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Remote(
command_executor=grid_url,
options=options
)
elif request.param == "firefox":
options = webdriver.FirefoxOptions()
driver = webdriver.Remote(
command_executor=grid_url,
options=options
)
elif request.param == "edge":
options = webdriver.EdgeOptions()
driver = webdriver.Remote(
command_executor=grid_url,
options=options
)
driver.maximize_window()
yield driver
driver.quit()
def test_parallel_execution(self, driver):
"""Test uitvoering op meerdere browsers"""
driver.get("https://the-internet.herokuapp.com/")
# Wait for title
wait = WebDriverWait(driver, 10)
assert "The Internet" in driver.title
# Test navigation
form_auth_link = wait.until(
EC.element_to_be_clickable((By.LINK_TEXT, "Form Authentication"))
)
form_auth_link.click()
assert "login" in driver.current_url.lower()
def run_parallel_tests():
"""Voer tests parallel uit met threading"""
def run_single_test(browser_name):
grid_url = "http://localhost:4444"
if browser_name == "chrome":
options = webdriver.ChromeOptions()
options.add_argument("--headless")
elif browser_name == "firefox":
options = webdriver.FirefoxOptions()
options.add_argument("--headless")
driver = webdriver.Remote(
command_executor=grid_url,
options=options
)
try:
driver.get("https://httpbin.org/delay/2")
print(f"{browser_name}: {driver.title}")
time.sleep(2)
finally:
driver.quit()
# Start parallel threads
threads = []
browsers = ["chrome", "firefox", "chrome", "firefox"]
for browser in browsers:
thread = threading.Thread(target=run_single_test, args=(browser,))
threads.append(thread)
thread.start()
# Wait for all threads
for thread in threads:
thread.join()
print("All parallel tests completed!")
if __name__ == "__main__":
run_parallel_tests()
Java Test Setup
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.net.URL;
import java.net.MalformedURLException;
public class GridTest {
private WebDriver driver;
private String gridUrl = "http://localhost:4444";
@Test
@Parameters({"browser"})
public void testOnGrid(String browserName) throws MalformedURLException {
if (browserName.equals("chrome")) {
ChromeOptions options = new ChromeOptions();
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");
driver = new RemoteWebDriver(new URL(gridUrl), options);
}
else if (browserName.equals("firefox")) {
FirefoxOptions options = new FirefoxOptions();
driver = new RemoteWebDriver(new URL(gridUrl), options);
}
try {
driver.get("https://www.google.com");
System.out.println("Page title: " + driver.getTitle());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (driver != null) {
driver.quit();
}
}
}
}
TestNG XML (testng.xml):
<?xml version="1.0" encoding="UTF-8"?>
<suite name="GridTestSuite" parallel="tests" thread-count="4">
<test name="ChromeTest">
<parameter name="browser" value="chrome"/>
<classes>
<class name="GridTest"/>
</classes>
</test>
<test name="FirefoxTest">
<parameter name="browser" value="firefox"/>
<classes>
<class name="GridTest"/>
</classes>
</test>
</suite>
Monitoring & Troubleshooting
Grid Console Features
Toegang via: http://localhost:4444/ui
Beschikbare informatie:
- Sessions: Actieve en afgeronde test sessies
- Node Status: Health check van alle nodes
- Capabilities: Beschikbare browser/OS combinaties
- Queue: Wachtende test requests
GraphQL API
# GraphQL endpoint
curl -X POST \
http://localhost:4444/graphql \
-H 'Content-Type: application/json' \
-d '{
"query": "{ grid { totalSlots, usedSlots } }"
}'
# Node details
curl -X POST \
http://localhost:4444/graphql \
-H 'Content-Type: application/json' \
-d '{
"query": "{ nodesInfo { nodes { id, status, maxSession, slotCount } } }"
}'
Health Monitoring Script
import requests
import json
import time
from datetime import datetime
def check_grid_health():
"""Monitor Grid health status"""
try:
# Grid status check
response = requests.get("http://localhost:4444/wd/hub/status")
status_data = response.json()
if status_data.get("value", {}).get("ready"):
print(f"✅ Grid is ready at {datetime.now()}")
# GraphQL node info
graphql_query = {
"query": """
{
grid {
totalSlots
usedSlots
}
nodesInfo {
nodes {
id
status
maxSession
slotCount
stereotypes
}
}
}
"""
}
graphql_response = requests.post(
"http://localhost:4444/graphql",
json=graphql_query
)
if graphql_response.status_code == 200:
data = graphql_response.json()
grid_info = data["data"]["grid"]
nodes_info = data["data"]["nodesInfo"]["nodes"]
print(f"📊 Total Slots: {grid_info['totalSlots']}")
print(f"🔄 Used Slots: {grid_info['usedSlots']}")
print(f"🖥️ Active Nodes: {len(nodes_info)}")
for node in nodes_info:
print(f" Node {node['id'][:8]}: {node['status']} ({node['slotCount']} slots)")
else:
print(f"❌ Grid not ready at {datetime.now()}")
except Exception as e:
print(f"💥 Error checking grid: {e}")
if __name__ == "__main__":
while True:
check_grid_health()
print("-" * 50)
time.sleep(30) # Check every 30 seconds
Veelvoorkomende Problemen & Oplossingen
1. “Connection refused” Error
# Check of hub draait
curl http://localhost:4444/wd/hub/status
# Controleer Java processen
jps -l | grep selenium
# Firewall check (Windows)
netstat -an | findstr 4444
2. Nodes registreren niet
# Controleer netwerk connectiviteit
ping localhost
telnet localhost 4444
# Docker network check
docker network ls
docker network inspect selenium-grid_default
3. Browser driver problemen
# Update drivers automatisch
java -jar selenium-server-4.17.0.jar node --selenium-manager true --detect-drivers
# Handmatige driver installatie
# Chrome: https://chromedriver.chromium.org/
# Firefox: https://github.com/mozilla/geckodriver/releases
4. Memory issues
# Increase Java heap size
java -Xmx2g -jar selenium-server-4.17.0.jar hub
# Docker memory limits
docker-compose -f docker-compose.yml up -d
docker stats
5. Session timeout problemen
# In docker-compose.yml
environment:
- SE_NODE_SESSION_TIMEOUT=60
- SE_NODE_MAX_SESSIONS=1
Best Practices
1. Resource Management
# Optimale Docker configuratie
services:
chrome-node:
image: selenium/node-chrome:4.17.0
environment:
- SE_NODE_MAX_SESSIONS=2 # Niet meer dan CPU cores
- SE_NODE_SESSION_TIMEOUT=60
deploy:
resources:
limits:
memory: 1G
cpus: '1.0'
2. Test Parallel Strategy
# Optimaal aantal parallel tests
import multiprocessing
max_parallel = min(
multiprocessing.cpu_count(),
available_grid_slots,
total_tests // 4 # Niet te veel parallel
)
3. Error Handling
from selenium.common.exceptions import WebDriverException
import time
def create_driver_with_retry(grid_url, options, max_retries=3):
"""Maak driver connection met retry logic"""
for attempt in range(max_retries):
try:
driver = webdriver.Remote(
command_executor=grid_url,
options=options
)
return driver
except WebDriverException as e:
if attempt < max_retries - 1:
print(f"Retry {attempt + 1}: {e}")
time.sleep(5)
else:
raise
4. CI/CD Integration
# GitHub Actions example
name: Selenium Grid Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start Selenium Grid
run: |
docker-compose up -d
# Wait for grid to be ready
timeout 60 bash -c 'until curl -f http://localhost:4444/wd/hub/status; do sleep 2; done'
- name: Run Tests
run: |
pytest tests/ --maxfail=1 -n 4
- name: Cleanup
if: always()
run: docker-compose down
Conclusie
Selenium Grid 4 biedt krachtige mogelijkheden voor gedistribueerde test uitvoering. De keuze tussen handmatige setup en Docker hangt af van je specifieke behoeften:
Gebruik handmatige setup wanneer:
- Je volledige controle wilt over de configuratie
- Je werkt in een enterprise omgeving met strikte security requirements
- Je custom browser versies nodig hebt
Gebruik Docker setup wanneer:
- Je snel wilt starten met minimal configuratie
- Je een reproduceerbare omgeving wilt
- Je eenvoudig wilt schalen
- Je CI/CD integratie nodig hebt
Volgende Stappen:
- Start met een eenvoudige Docker setup
- Experimenteer met verschillende browser combinaties
- Implementeer parallel testing in je test suite
- Voeg monitoring en alerting toe
- Integreer met je CI/CD pipeline
Met deze handleiding kun je een robuuste, schaalbare test infrastructuur opzetten die je development workflow aanzienlijk zal verbeteren.
Nuttige Links: