← Blog

"Selenium Series #16: CI/CD Integration — Jenkins Pipelines and Maven Surefire"

Automate your Selenium tests with Jenkins. Configure Jenkinsfile pipelines, run headless tests on every commit, publish HTML reports, and trigger notifications on failure.

– reading now
– views
– comments

Series Navigation

← Part 15: Selenium Grid

→ Part 17: Headless Browsers and Docker


Jenkinsfile — Declarative Pipeline

// Jenkinsfile
pipeline {
    agent any

    tools {
        maven 'Maven-3.8'
        jdk   'JDK-11'
    }

    parameters {
        choice(name: 'BROWSER',      choices: ['chrome', 'firefox', 'edge'], description: 'Browser to test')
        choice(name: 'ENVIRONMENT',  choices: ['staging', 'prod'],           description: 'Target environment')
        booleanParam(name: 'HEADLESS', defaultValue: true, description: 'Run headless?')
    }

    environment {
        BASE_URL  = "${params.ENVIRONMENT == 'staging' ? 'https://staging.app.com' : 'https://app.com'}"
        TIMESTAMP = sh(script: 'date +%Y%m%d_%H%M%S', returnStdout: true).trim()
    }

    stages {

        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/yourname/selenium-project.git'
                echo "Running on: ${env.NODE_NAME}"
            }
        }

        stage('Validate') {
            steps {
                sh 'mvn --version'
                sh 'java -version'
                sh 'google-chrome --version || chromium --version'
            }
        }

        stage('Download Dependencies') {
            steps {
                sh 'mvn dependency:resolve -q'
            }
        }

        stage('Run Selenium Tests') {
            steps {
                sh """
                    mvn test \
                      -Dbrowser=${params.BROWSER} \
                      -Dheadless=${params.HEADLESS} \
                      -Dbase.url=${env.BASE_URL} \
                      -DsuiteXmlFile=src/test/resources/testng.xml \
                      2>&1 | tee test-output/maven-output.log
                """
            }
            post {
                always {
                    // Archive screenshots on failure
                    archiveArtifacts artifacts: 'test-output/screenshots/**/*.png',
                                     allowEmptyArchive: true
                }
            }
        }

        stage('Publish Reports') {
            steps {
                // Publish TestNG HTML report
                publishHTML(target: [
                    allowMissing: false,
                    alwaysLinkToLastBuild: true,
                    keepAll: true,
                    reportDir: 'test-output',
                    reportFiles: 'index.html',
                    reportName: 'TestNG Report'
                ])
            }
        }
    }

    post {
        failure {
            emailext(
                subject: "FAILED: Selenium Tests — ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                body: """
                    <h2>Selenium Test Failure</h2>
                    <p><b>Job:</b> ${env.JOB_NAME}</p>
                    <p><b>Build:</b> #${env.BUILD_NUMBER}</p>
                    <p><b>Browser:</b> ${params.BROWSER}</p>
                    <p><b>Environment:</b> ${params.ENVIRONMENT}</p>
                    <p><b>Console:</b> <a href="${env.BUILD_URL}console">${env.BUILD_URL}console</a></p>
                    <p><b>Report:</b> <a href="${env.BUILD_URL}TestNG_Report">View TestNG Report</a></p>
                """,
                to: "team@example.com",
                mimeType: 'text/html'
            )
        }
        always {
            // Archive full test output
            archiveArtifacts artifacts: 'test-output/**', allowEmptyArchive: true
            // Clean workspace
            cleanWs()
        }
    }
}

Maven Surefire Plugin Configuration

<!-- pom.xml -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        <!-- TestNG suite file -->
        <suiteXmlFiles>
            <suiteXmlFile>${suiteXmlFile}</suiteXmlFile>
        </suiteXmlFiles>

        <!-- System properties passed to tests -->
        <systemPropertyVariables>
            <browser>${browser}</browser>
            <headless>${headless}</headless>
            <base.url>${base.url}</base.url>
            <environment>${environment}</environment>
        </systemPropertyVariables>

        <!-- Rerun failing tests up to 2 times -->
        <rerunFailingTestsCount>2</rerunFailingTestsCount>

        <!-- Fail build if tests fail -->
        <testFailureIgnore>false</testFailureIgnore>
    </configuration>
</plugin>

Default values in pom.xml properties:

<properties>
    <browser>chrome</browser>
    <headless>true</headless>
    <base.url>https://staging.example.com</base.url>
    <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</properties>

Reading System Properties in Tests

public class BaseTest {
    protected static Properties config = new Properties();

    static {
        // System properties (from -Dproperty=value) override config file
        config.setProperty("browser",
            System.getProperty("browser", "chrome"));
        config.setProperty("headless",
            System.getProperty("headless", "false"));
        config.setProperty("base.url",
            System.getProperty("base.url", "https://staging.example.com"));
    }
}

GitLab CI Integration

# .gitlab-ci.yml
image: maven:3.8-openjdk-11

stages:
  - test

selenium-tests:
  stage: test
  before_script:
    - apt-get update -qq && apt-get install -y -qq chromium chromium-driver
    - export CHROME_BIN=/usr/bin/chromium
  script:
    - mvn test
        -Dbrowser=chrome
        -Dheadless=true
        -Dbase.url=$STAGING_URL
  artifacts:
    when: always
    paths:
      - test-output/
    reports:
      junit: test-output/junitreports/*.xml
    expire_in: 7 days
  only:
    - main
    - merge_requests

What's Next

In Part 17 we run tests without a display — headless Chrome and Firefox on Linux CI servers, and fully containerised tests in Docker with zero system dependencies.

Discussion

Loading...

Leave a Comment

All comments are reviewed before appearing. No links please.

0 / 1000