DevOps · Selenium Grid & UI Tests in CI
Why Every DevOps Engineer Should Learn Selenium in 2026
Quick summary — why DevOps engineers should learn Selenium
Every DevOps engineer should learn Selenium in 2026 because UI tests run inside the pipelines DevOps owns. You do not need to write every test. You need to run Selenium Grid in Docker or Kubernetes, connect tests through RemoteWebDriver, keep browser stages fast and stable, and read failures well enough to tell an infrastructure problem from a real application bug.
In this guide you will learn:
- Why it is a DevOps job — test infrastructure, not test writing.
- Selenium Grid in Docker — hub, nodes, shared memory and readiness.
- UI tests in CI — GitHub Actions and Jenkins stage examples.
- Templates — Grid health check, triage sheet and Helm values.
- Interview questions — Selenium topics asked in DevOps rounds.
SECTION 01Why Selenium is a DevOps concern, not just a QA one
Selenium is the long-established open-source tool for automating real browsers through the W3C WebDriver standard. Many companies have large Selenium suites written over years in Java, Python or C#. Those suites must run somewhere on every merge or release, and that ‘somewhere’ — CI runners, browser containers, a Selenium Grid — is usually managed by the DevOps or platform team.
When a UI stage fails, the first question in the team chat is often ‘is it the test or the infrastructure?’ A DevOps engineer who knows how Selenium connects to browsers can answer quickly: the Grid was not ready, the container ran out of shared memory, the browser version did not match, or the app really is broken. That skill saves hours of back-and-forth and builds trust with the QA team.
| Responsibility | Usually owned by | What DevOps needs to know | Typical tool |
|---|---|---|---|
| Writing test cases | QA / SDET | Enough to read a failing test | Selenium with pytest or TestNG |
| Running tests on each change | DevOps | How to add a stable CI stage | GitHub Actions, Jenkins, GitLab CI |
| Providing browsers at scale | DevOps / platform | Grid architecture and scaling | Selenium Grid in Docker or Kubernetes |
| Deciding if a release can go | Release owner with QA | How test results gate a deploy | JUnit reports, pipeline rules |
# Start one Chrome browser with WebDriver in a container
# (pin a specific tag in real pipelines instead of latest)
docker run -d --name selenium \
-p 4444:4444 --shm-size="2g" \
selenium/standalone-chrome:latest
# Is it ready to accept sessions?
curl -s http://localhost:4444/status | python3 -m json.tool
# look for: "ready": true
# Install the client library for the test
pip install selenium pytest
# tests/test_home.py
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
GRID_URL = os.environ.get("GRID_URL", "http://localhost:4444")
APP_URL = os.environ.get("APP_URL", "https://example.com")
def test_home_page_has_heading():
options = webdriver.ChromeOptions()
driver = webdriver.Remote(command_executor=GRID_URL, options=options)
try:
driver.get(APP_URL)
heading = driver.find_element(By.TAG_NAME, "h1")
assert heading.text.strip() != ""
finally:
driver.quit()
# Run: pytest -q tests/
SECTION 02Running Selenium Grid in Docker and Kubernetes
A single standalone container is fine for a handful of tests. Larger suites need Selenium Grid: a hub (router and queue) that receives session requests and nodes that run the actual browsers. The official docker-selenium images make this easy with Docker Compose, and nodes register with the hub through an event bus on ports 4442 and 4443.
Two settings cause most trouble. Browsers need more shared memory than Docker's default, so set shm_size: 2gb on browser nodes or Chrome may crash mid-test. And tests must wait until the Grid reports ready before starting. On Kubernetes, the project publishes a Helm chart, which is the usual way to run a Grid shared by several teams and to scale nodes up and down.
| Grid component | Role | Port / setting | Common problem |
|---|---|---|---|
| Hub | Accepts sessions, queues and routes them | 4444 for clients | Tests start before hub is ready |
| Event bus | Nodes register with the hub | 4442 and 4443 | Node env vars point at wrong host |
| Browser node | Runs Chrome, Firefox or Edge | shm_size 2gb, SE_NODE_MAX_SESSIONS | Browser crashes from low shared memory |
| Helm chart | Deploys Grid on Kubernetes | Values file for nodes | Too few nodes for parallel CI jobs |
# docker-compose.yml — pin matching tags for hub and nodes
services:
selenium-hub:
image: selenium/hub:latest
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
chrome:
image: selenium/node-chrome:latest
shm_size: 2gb
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=2
firefox:
image: selenium/node-firefox:latest
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
# docker compose up -d --scale chrome=3
# Install the official Selenium Grid Helm chart
helm repo add docker-selenium https://www.selenium.dev/docker-selenium
helm repo update
kubectl create namespace selenium
helm install selenium-grid docker-selenium/selenium-grid -n selenium
# Check hub and node pods
kubectl get pods -n selenium
# Reach the Grid from your laptop for a quick check
kubectl port-forward -n selenium svc/selenium-hub 4444:4444
curl -s http://localhost:4444/status
SECTION 03Adding a reliable Selenium stage to CI pipelines
A good UI test stage has a clear shape: deploy the build to a test environment, start or connect to the Grid, wait for readiness, run tests in parallel, then publish a JUnit report and screenshots whatever the result. The stage should fail the pipeline on genuine test failures but give enough evidence that someone can decide in minutes whether to fix the app or the infrastructure.
In GitHub Actions you can run the standalone browser as a service container next to the job. In Jenkins, a common pattern is to start the Grid with Docker Compose in one stage and tear it down in a post block so containers never pile up on the agent. Either way, parallelism with pytest-xdist or TestNG threads only helps if the Grid has enough sessions free.
| Pipeline step | Purpose | Example command | If it fails |
|---|---|---|---|
| Wait for Grid | Avoid SessionNotCreated errors | curl /status until ready | Check node logs and registration |
| Run tests in parallel | Keep the stage short | pytest -n 4 | Lower workers or add nodes |
| Publish JUnit XML | Show results in CI UI | pytest --junitxml=report.xml | Check report path in config |
| Tear down Grid | Free agent resources | docker compose down | Clean up stopped containers manually |
# .github/workflows/ui-tests.yml
name: ui-tests
on: [push]
jobs:
selenium:
runs-on: ubuntu-latest
services:
selenium:
image: selenium/standalone-chrome:latest
ports:
- 4444:4444
options: --shm-size=2g
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install selenium pytest pytest-xdist
- name: Wait for Selenium
run: |
for i in $(seq 1 30); do
curl -s http://localhost:4444/status | grep -q '"ready": *true' && exit 0
sleep 2
done
exit 1
- run: pytest -n 2 --junitxml=report.xml tests/
env:
GRID_URL: http://localhost:4444
APP_URL: https://staging.example.com
// Jenkinsfile (declarative, excerpt)
pipeline {
agent any
stages {
stage('Start Grid') {
steps {
sh 'docker compose -f selenium-grid.yml up -d --scale chrome=3'
sh '''
for i in $(seq 1 30); do
curl -s http://localhost:4444/status | grep -q '"ready": *true' && exit 0
sleep 2
done
exit 1
'''
}
}
stage('UI Tests') {
steps {
sh 'pytest -n 4 --junitxml=report.xml tests/'
}
}
}
post {
always {
junit 'report.xml'
sh 'docker compose -f selenium-grid.yml down'
}
}
}
SECTION 04Templates: Grid health check, failure triage, Helm values
Keep these in your repository so anyone on the team can check, debug and size the Selenium setup without guessing.
#!/usr/bin/env bash
# grid-health.sh — fail fast if the Grid is not usable
GRID=${GRID_URL:-http://localhost:4444}
for i in $(seq 1 30); do
if curl -s "$GRID/status" | grep -q '"ready": *true'; then
echo "Grid ready at $GRID"
exit 0
fi
echo "Waiting for Grid... ($i)"
sleep 2
done
echo "Grid not ready after 60s" >&2
docker compose -f selenium-grid.yml logs --tail=50 || true
exit 1
SELENIUM STAGE FAILURE TRIAGE
Pipeline / build : ____________
Failed tests : ____ of ____
1. Error type?
[ ] SessionNotCreated / timeout -> Grid capacity or readiness
[ ] Chrome crashed / tab crashed -> shared memory (shm_size)
[ ] NoSuchElement / assertion -> likely app or test change
[ ] Connection refused to app -> environment not deployed
2. Same test failed on last green build? yes / no
3. Passed on retry? yes / no (if yes, mark as flaky, raise ticket)
4. Screenshot / logs attached? yes / no
Verdict: Infra issue / App bug / Test needs fix
Owner : ____________
# values-ci.yaml — example overrides for the selenium-grid chart
# Check key names against the chart version you install:
# helm show values docker-selenium/selenium-grid
chromeNode:
enabled: true
replicas: 3
resources:
requests:
cpu: "1"
memory: 2Gi
firefoxNode:
enabled: false
edgeNode:
enabled: false
# helm upgrade --install selenium-grid docker-selenium/selenium-grid \
# -n selenium -f values-ci.yaml
SECTION 05Tips for DevOps engineers working with Selenium
Focus on what keeps browser test stages stable and fast:
- Pin image tags — use the same explicit Selenium version for hub and nodes, and upgrade them together on purpose.
- Give browsers memory — set shm_size to 2gb or mount /dev/shm for every browser container.
- Gate on readiness — never start tests until /status reports ready; it removes a whole class of random failures.
- Size the Grid to parallelism — free browser sessions should match or exceed your parallel test workers.
- Always collect evidence — publish JUnit results and screenshots even when the stage passes, so trends are visible.
SECTION 06Interview Q&A — Selenium in DevOps interviews
Q1What is Selenium Grid and why would DevOps run it?
Selenium Grid routes browser sessions from tests to many browser nodes so suites run in parallel across browsers. DevOps runs it because it is shared test infrastructure: it needs provisioning, scaling, upgrades and monitoring, just like any other service in the pipeline.
Q2Why do Selenium browser containers need a larger shm_size?
Chrome and Firefox use shared memory heavily. Docker's default /dev/shm is small, so browsers can crash or tabs fail under load. Setting shm_size to around 2 GB, or mounting the host's /dev/shm, keeps browser sessions stable.
Q3A UI test stage fails with SessionNotCreatedException. What do you check?
First whether the Grid was ready and had free slots, using the /status endpoint and node logs. Then browser and driver compatibility, the requested capabilities and whether hub and nodes run matching versions. Only after that would I suspect the test itself.
Q4How do you keep a Selenium stage from slowing the pipeline?
Run tests in parallel against enough Grid nodes, run only a tagged smoke subset on pull requests, schedule the full suite on main or nightly, and remove waits based on fixed sleeps in favour of explicit waits written by the QA team.
Q5What is the difference between Selenium standalone and Grid?
Standalone runs one browser type with WebDriver in a single process or container, good for small suites. Grid separates a hub that queues and routes sessions from multiple nodes that run browsers, allowing parallel, multi-browser runs at scale.
SECTION 07Test yourself — Selenium for DevOps quiz
Five questions. No sign-up.
0 / 5Pick an answer to see why it is right or wrong.
SECTION 08Frequently asked questions
Do DevOps engineers need to write Selenium tests?
Usually not. QA engineers or SDETs write most tests. DevOps engineers run the infrastructure: CI stages, browser containers and Selenium Grid. Being able to read and run a test, and write a small smoke check, is very useful for debugging pipelines.
How do I run Selenium Grid in Docker?
Use the official docker-selenium images. For a quick start run selenium/standalone-chrome with port 4444 and a 2 GB shm size. For a full Grid, use Docker Compose with selenium/hub and browser node images that point at the hub's event bus.
Is Selenium still relevant in 2026 with Playwright available?
Yes. Playwright is popular for new projects, but many organisations have large existing Selenium suites in Java, Python and C#, and Selenium implements the W3C WebDriver standard. DevOps engineers often need to support both in pipelines.
Can Selenium Grid run on Kubernetes?
Yes. The docker-selenium project publishes a Helm chart that deploys the hub and browser nodes on Kubernetes. Teams use it to share one Grid across pipelines and adjust the number of browser nodes to match test parallelism.
Which language should a DevOps engineer use with Selenium?
Use whatever language the existing test suite uses, often Java or Python. For your own small smoke checks, Python with pytest is a practical choice because it fits well with scripting and automation work DevOps engineers already do.
SECTION 09Related reads
Classroom & online · Noida
Run test automation the DevOps way
Our DevOps Training Course covers Linux, Git, CI/CD, Docker, Kubernetes and cloud, with hands-on pipelines that include automated test stages.
Talk to a counsellor for current fees- CI/CD pipelines
- Docker & Kubernetes labs
- Mock interviews
- Weekday & weekend batches