Continuous Integration with Selenium
Integrate your Selenium tests into CI/CD pipelines for automated testing on every code change.
Jenkins Integration
Jenkinsfile:
pipeline {
agent any
tools {
maven 'Maven 3.9.0'
jdk 'JDK 17'
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'https://github.com/your-repo/selenium-framework.git'
}
}
stage('Build') {
steps {
sh 'mvn clean compile'
}
}
stage('Run Tests') {
steps {
sh 'mvn test -Dbrowser=chrome -Dheadless=true'
}
}
stage('Generate Reports') {
steps {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'reports/extent-reports',
reportFiles: 'test-report.html',
reportName: 'Test Report'
])
}
}
}
post {
always {
junit 'target/surefire-reports/*.xml'
archiveArtifacts artifacts: 'screenshots/**/*.png', allowEmptyArchive: true
}
failure {
emailext(
subject: "Test Failure: ${currentBuild.fullDisplayName}",
body: "Tests failed. Check console output.",
to: "team@example.com"
)
}
}
}
GitHub Actions
.github/workflows/selenium-tests.yml:
name: Selenium E2E Tests
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * *' # Run daily at 2 AM
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
browser: [chrome, firefox]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Install Chrome
if: matrix.browser == 'chrome'
uses: browser-actions/setup-chrome@latest
- name: Install Firefox
if: matrix.browser == 'firefox'
uses: browser-actions/setup-firefox@latest
- name: Run tests
run: mvn test -Dbrowser=${{ matrix.browser }} -Dheadless=true
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v3
with:
name: screenshots-${{ matrix.browser }}
path: screenshots/
- name: Upload test reports
if: always()
uses: actions/upload-artifact@v3
with:
name: test-reports-${{ matrix.browser }}
path: reports/
- name: Publish test results
if: always()
uses: dorny/test-reporter@v1
with:
name: Test Results (${{ matrix.browser }})
path: target/surefire-reports/*.xml
reporter: java-junit
GitLab CI
.gitlab-ci.yml:
image: maven:3.9.0-eclipse-temurin-17
stages:
- build
- test
- report
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
paths:
- .m2/repository
build:
stage: build
script:
- mvn clean compile
test:chrome:
stage: test
script:
- apt-get update && apt-get install -y chromium chromium-driver
- mvn test -Dbrowser=chrome -Dheadless=true
artifacts:
when: always
paths:
- target/surefire-reports/
- screenshots/
- reports/
reports:
junit: target/surefire-reports/*.xml
test:firefox:
stage: test
script:
- apt-get update && apt-get install -y firefox-esr
- mvn test -Dbrowser=firefox -Dheadless=true
artifacts:
when: always
paths:
- target/surefire-reports/
- screenshots/
- reports/
pages:
stage: report
script:
- mkdir -p public
- cp -r reports/extent-reports/* public/
artifacts:
paths:
- public
only:
- main
Docker Integration
Dockerfile:
FROM maven:3.9.0-eclipse-temurin-17
# Install browsers and drivers
RUN apt-get update && apt-get install -y \
chromium \
chromium-driver \
firefox-esr \
wget \
&& rm -rf /var/lib/apt/lists/*
# Install geckodriver
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-linux64.tar.gz \
&& tar -xvzf geckodriver-v0.33.0-linux64.tar.gz \
&& mv geckodriver /usr/local/bin/ \
&& chmod +x /usr/local/bin/geckodriver
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY . .
CMD ["mvn", "test", "-Dheadless=true"]
docker-compose.yml:
version: '3.8'
services:
selenium-hub:
image: selenium/hub:latest
ports:
- "4444:4444"
environment:
- GRID_MAX_SESSION=5
- GRID_BROWSER_TIMEOUT=300
- GRID_TIMEOUT=300
chrome:
image: selenium/node-chrome:latest
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=3
shm_size: 2gb
firefox:
image: selenium/node-firefox:latest
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=3
shm_size: 2gb
tests:
build: .
depends_on:
- selenium-hub
- chrome
- firefox
environment:
- GRID_URL=http://selenium-hub:4444
- GRID_ENABLED=true
volumes:
- ./reports:/app/reports
- ./screenshots:/app/screenshots
Maven Configuration for CI
pom.xml profiles:
<profiles>
<!-- Local Development -->
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<headless>false</headless>
<browser>chrome</browser>
</properties>
</profile>
<!-- CI Environment -->
<profile>
<id>ci</id>
<properties>
<headless>true</headless>
<parallel>classes</parallel>
<thread.count>3</thread.count>
</properties>
</profile>
<!-- Selenium Grid -->
<profile>
<id>grid</id>
<properties>
<grid.enabled>true</grid.enabled>
<grid.url>http://localhost:4444</grid.url>
</properties>
</profile>
</profiles>
Run with profile:
# Local
mvn test
# CI
mvn test -Pci
# Grid
mvn test -Pgrid
Test Reporting
Allure Reports Integration:
Add to pom.xml:
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.24.0</version>
</dependency>
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>2.12.0</version>
</plugin>
Generate and serve report:
mvn allure:serve
Notification Integration
Slack Notifications (Jenkins):
post {
success {
slackSend(
color: 'good',
message: "Tests Passed: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
channel: '#qa-automation'
)
}
failure {
slackSend(
color: 'danger',
message: "Tests Failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}\n${env.BUILD_URL}",
channel: '#qa-automation'
)
}
}
Performance Monitoring
Track test execution time:
@Listeners(PerformanceListener.class)
public class PerformanceTest {
@Test
public void measuredTest() {
long startTime = System.currentTimeMillis();
// Test execution
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("Test duration: " + duration + "ms");
// Fail if test takes too long
Assert.assertTrue(duration < 10000, "Test took too long: " + duration + "ms");
}
}
Best Practices for CI/CD
- ✅ Run tests in headless mode - Faster execution in CI
- ✅ Use Docker containers - Consistent environments
- ✅ Implement parallel execution - Reduce build time
- ✅ Archive test artifacts - Screenshots, reports, logs
- ✅ Set up notifications - Alert team of failures
- ✅ Run smoke tests on every commit - Quick feedback
- ✅ Schedule full regression nightly - Comprehensive coverage
- ✅ Use Selenium Grid - Distribute tests across nodes
- ✅ Monitor test performance - Track execution time
- ✅ Version your test code - Track changes and rollback
Key Takeaways
✅ CI/CD integration enables automated testing on every change
✅ Docker ensures consistent test environments
✅ Parallel execution reduces feedback time
✅ Proper reporting and notifications keep team informed
What is the benefit of running tests in headless mode?
What is Selenium Grid used for?
Congratulations! 🎉
You’ve completed the Java + Selenium E2E Testing Mastery course! You now have the skills to:
- Build robust test automation frameworks
- Implement Page Object Model pattern
- Use TestNG for test organization
- Handle complex scenarios
- Integrate tests into CI/CD pipelines
Keep practicing and happy testing! 🚀