← 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