How to Set Up Jenkins for Selenium Testing

How to Set Up Jenkins for Selenium Testing

I’ve maintained test suites where “run Selenium tests” meant someone manually kicking off a script on their laptop, hoping their browser version matched what the tests expected. That approach falls apart the moment more than one person touches the codebase. Automating Selenium through Jenkins fixed that for good – every commit now gets tested against real browsers, consistently, without anyone needing to remember to run anything by hand. Here’s how I built that pipeline.

Why Run Selenium Tests Through Jenkins

Selenium automates real browser interactions, which makes it powerful but also fragile if run inconsistently. Jenkins solves the consistency problem by giving you:

Architecture: How the Pieces Fit Together

A typical Selenium-on-Jenkins setup has:

Step 1: Prerequisites

Step 2: Install Required Jenkins Plugins

From Manage JenkinsPlugins, install:

Or via CLI:

java -jar jenkins-cli.jar -s http://localhost:8080/ install-plugin junit htmlpublisher docker-workflow -restart

Step 3: Stand Up Selenium Grid with Docker Compose

Running Selenium Grid in containers avoids the headache of installing browser binaries directly on your Jenkins agents. Here’s a docker-compose.yml for a hub plus Chrome and Firefox nodes:

version: "3"
services:
  selenium-hub:
    image: selenium/hub:4.21.0
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

  chrome:
    image: selenium/node-chrome:4.21.0
    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

  firefox:
    image: selenium/node-firefox:4.21.0
    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

Start it up before your tests run: docker compose up -d. Your test code then connects to http://localhost:4444/wd/hub as the Remote WebDriver endpoint.

Step 4: Write the Jenkinsfile

Here’s a complete declarative pipeline for a Java/Maven + TestNG Selenium suite, running against the Grid:

pipeline {
    agent any

    environment {
        SELENIUM_GRID_URL = 'http://localhost:4444/wd/hub'
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/myorg/selenium-tests.git'
            }
        }

        stage('Start Selenium Grid') {
            steps {
                sh 'docker compose -f docker/selenium-grid.yml up -d'
                sh 'sleep 15' // give the grid time to register nodes
            }
        }

        stage('Run Tests') {
            steps {
                sh 'mvn clean test -Dselenium.grid.url=$SELENIUM_GRID_URL -Dbrowser=chrome'
            }
        }

        stage('Run Tests - Firefox') {
            steps {
                sh 'mvn test -Dselenium.grid.url=$SELENIUM_GRID_URL -Dbrowser=firefox'
            }
        }
    }

    post {
        always {
            junit 'target/surefire-reports/*.xml'
            archiveArtifacts artifacts: 'target/screenshots/**', allowEmptyArchive: true
            sh 'docker compose -f docker/selenium-grid.yml down'
        }
    }
}

Running Tests in Parallel Across Browsers

To actually cut down execution time rather than just running the same suite twice sequentially, use Jenkins’ parallel block:

stage('Cross-Browser Tests') {
    parallel {
        stage('Chrome') {
            steps {
                sh 'mvn test -Dbrowser=chrome'
            }
        }
        stage('Firefox') {
            steps {
                sh 'mvn test -Dbrowser=firefox'
            }
        }
        stage('Edge') {
            steps {
                sh 'mvn test -Dbrowser=edge'
            }
        }
    }
}

Capturing Screenshots and Videos on Failure

Most flaky UI test failures are only debuggable if you have visual evidence. In your test framework’s @AfterMethod (TestNG) or tearDown hook, capture a screenshot when a test fails and save it to a directory Jenkins archives:

@AfterMethod
public void tearDown(ITestResult result) {
    if (result.getStatus() == ITestResult.FAILURE) {
        File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(src, new File("target/screenshots/" + result.getName() + ".png"));
    }
    driver.quit();
}

Selenium Grid’s video-recording node images (selenium/video) can also record full session videos, which are archived the same way as screenshots.

Publishing Rich HTML Reports

If you use Allure Reports instead of plain JUnit XML, add the Allure Jenkins plugin and this stage:

stage('Publish Allure Report') {
    steps {
        allure includeProperties: false, jdk: '', results: [[path: 'target/allure-results']]
    }
}

Integrating with the Wider Toolchain

Monitoring and Troubleshooting

Security Best Practices

Best Practices

FAQs

Do I need Selenium Grid, or can Jenkins run browsers directly on the agent? You can install browsers directly on the agent for small setups, but Grid gives you parallelism, isolation, and easier scaling, so it’s worth adopting even for mid-sized suites.

Can I run Selenium tests headless in Jenkins? Yes, and it’s recommended for CI – both Chrome and Firefox support a --headless flag, which speeds up execution and avoids needing a display server.

How do I test on real mobile browsers, not just desktop? Use Selenium Grid with Appium nodes, or integrate a cloud device grid service (BrowserStack, Sauce Labs) as a remote WebDriver endpoint instead of your own Grid.

What’s the best way to handle test flakiness? Combine explicit waits, retry logic for known-flaky tests, and screenshot/video capture, then track flaky test rates over time rather than ignoring them.

Can this pipeline scale to hundreds of parallel test cases? Yes, especially if Selenium Grid runs on Kubernetes where you can autoscale browser node pods based on queue depth.

Summary

Setting up Selenium testing in Jenkins comes down to three pieces: a reliable Selenium Grid (ideally containerized), a Jenkinsfile that starts the Grid, runs your suite, and archives results, and good reporting so failures are actionable rather than just red X’s. Once this is in place, UI regressions get caught automatically on every push instead of relying on someone remembering to test manually, and your whole team gets a shared, trustworthy source of truth on browser compatibility.

References

Exit mobile version