Continuous Integration & Deployment Automation
Java Automation Testing – From Beginner to Advanced
Goal:
Build a fully‑automated CI/CD pipeline that compiles, tests, deploys, runs smoke tests, and generates quality reports for a Java web application.
Audience:
1️⃣ Beginners – want to understand the core concepts and get a simple pipeline running.
2️⃣ Intermediate – need a working implementation that can be extended.
3️⃣ Advanced – want optimisations, best‑practice patterns, and real‑world insights.
Prerequisites – Java 21+, Maven/Gradle, Git, Docker (optional), Kubernetes (optional), Selenium 4.x, JUnit5 or TestNG, Jenkins 2.440+.
Table of Contents
| Section | Topics |
|---|---|
| 1. Fundamentals | CI/CD concepts, Jenkins basics, pipeline syntax, test automation, deployment, smoke tests, reporting |
| 2. Implementation | Jenkins setup, Jenkinsfile, Maven/Gradle build, Selenium tests, Docker/K8s deployment, smoke tests, reporting |
| 3. Advanced Topics | Pipeline as code best practices, parallel/distributed tests, Docker‑in‑pipeline, canary/blue‑green, caching, shared libs |
| 4. Real‑World Applications | E‑commerce, banking, microservices, continuous delivery, regression suites |
| 5. Exercises | Step‑by‑step projects, code challenges, optimisation tasks |
All code snippets are in Java (or Groovy for Jenkins) and are fully commented.
1. Fundamentals
1.1 Continuous Integration & Continuous Deployment
| Concept | What it means | Why it matters |
|---|---|---|
| CI | Developers merge code into a shared repo frequently (at least once a day). The CI server automatically builds and runs tests. | Detects integration bugs early. |
| CD | After a successful build, the code is automatically deployed to an environment (staging/production). | Reduces manual deployment errors and speeds time‑to‑market. |
| Pipeline | A scripted definition of the CI/CD steps – usually in a Jenkinsfile. | Keeps the pipeline versioned with the code. |
Industry Insight – Most Fortune‑500 companies run their pipelines in Jenkinsfile format (Declarative or Scripted). It’s the single source of truth for the build process.
1.2 Jenkins Basics
- Master – The Jenkins server that orchestrates jobs.
- Agent – A worker node that executes the pipeline stages.
- Credentials – Securely store tokens, SSH keys, etc. Use Jenkins Credentials Plugin.
Jenkinsfile Syntax
pipeline {
agent any
environment {
MAVEN_HOME = '/opt/maven'
}
stages {
stage('Checkout') { steps { checkout scm } }
stage('Build') { steps { sh 'mvn clean package' } }
stage('Test') { steps { sh 'mvn test' } }
}
}
Tip: Use
agent anyfor small projects, but for heavy workloads, specify a dedicated agent (label 'docker').
1.3 Test Automation Overview
- Selenium – Browser automation.
- TestNG/JUnit5 – Test frameworks.
- Page Object Model – Encapsulate page interactions.
Professional Insight – Keep test code in a separate module (
src/test/java). This keeps the production code clean and allows you to run tests in isolation.
1.4 Deployment Basics
| Target | Tool | Typical Command |
|---|---|---|
| Tomcat | mvn tomcat7:deploy | Deploy WAR |
| Docker | docker build && docker push | Build & push image |
| Kubernetes | kubectl apply | Apply manifest |
Edge Case – When deploying to a shared staging environment, you must use unique tags or namespace to avoid collisions.
1.5 Smoke Tests
- Quick sanity checks after deployment:
- Verify the application is reachable (
curl -I http://app). - Basic functional flows (login, checkout).
- Verify the application is reachable (
- Run them in a separate pipeline stage.
1.6 Test Reporting
| Tool | Output | Integration |
|---|---|---|
| Allure | HTML reports | allure serve |
| ExtentReports | Rich UI | Maven plugin |
| JUnit XML | Jenkins built‑in | publishJUnitResults |
Pro Tip – Store the reports as artifacts and archive them in Jenkins. This keeps the build history.
2. Implementation
Goal: Build a pipeline that compiles, tests, deploys, runs smoke tests, and generates reports.
2.1 Jenkins Setup
Install Jenkins (via Docker or native).
Install Plugins:
- Pipeline
- Maven Integration
- Docker Pipeline Steps
- Allure Jenkins Plugin
- Credentials Binding
Create Credentials:
dockerHub– username/password.k8sCluster– kubeconfig.
2.2 Jenkinsfile – Declarative Pipeline
pipeline {
agent { label 'docker' }
environment {
DOCKER_IMAGE = "myorg/${PROJECT_NAME}:${BUILD_NUMBER}"
REGISTRY = 'docker.io'
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Unit Tests') {
steps {
sh 'mvn test'
junit 'target/surefire-reports/*.xml'
}
}
stage('Docker Build') {
steps {
script {
sh """
docker build -t ${DOCKER_IMAGE} .
docker push ${DOCKER_IMAGE}
"""
}
}
}
stage('Deploy to Staging') {
steps {
sh """
kubectl set image deployment/${PROJECT_NAME} ${PROJECT_NAME}=${DOCKER_IMAGE} --record
kubectl rollout status deployment/${PROJECT_NAME}
"""
}
}
stage('Smoke Tests') {
steps {
sh 'mvn test -Dgroups=smoke'
junit 'target/surefire-reports/*.xml'
}
}
stage('Generate Reports') {
steps {
allure([
reportBuild: true,
reportTitle: "${PROJECT_NAME} Build ${BUILD_NUMBER}"
])
}
}
}
post {
always {
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
failure {
mail to: 'devops@example.com',
subject: "Build ${BUILD_NUMBER} Failed",
body: "Check Jenkins for details."
}
}
}
Explanation
| Section | What it does |
|---|---|
| agent { label ‘docker’ } | Runs on a Docker‑capable node. |
| environment | Sets variables used throughout. |
| stage(‘Unit Tests’) | Runs all tests (mvn test). |
| stage(‘Docker Build’) | Builds the Docker image and pushes it. |
| stage(‘Deploy to Staging’) | Uses kubectl to deploy the image. |
| stage(‘Smoke Tests’) | Runs a subset of tests (-Dgroups=smoke). |
| stage(‘Generate Reports’) | Publishes Allure reports. |
| post | Handles cleanup and notifications. |
2.3 Maven Build – Sample pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>webapp</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<java.version>21</java.version>
<selenium.version>4.20.0</selenium.version>
<testng.version>7.7.0</testng.version>
</properties>
<dependencies>
<!-- Production -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.3.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven Surefire for unit tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<groups>smoke</groups>
</configuration>
</plugin>
<!-- Allure -->
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>2.10.0</version>
</plugin>
<!-- Docker plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.32.0</version>
</plugin>
</plugins>
</build>
</project>
2.4 Selenium Test – Page Object Model
package com.example.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
private WebDriver driver;
@FindBy(id = "username")
private WebElement usernameInput;
@FindBy(id = "password")
private WebElement passwordInput;
@FindBy(css = "button[type='submit']")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void login(String user, String pass) {
usernameInput.sendKeys(user);
passwordInput.sendKeys(pass);
loginButton.click();
}
}
Test Class
package com.example.tests;
import com.example.page.LoginPage;
import org.testng.annotations.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class SmokeLoginTest {
@Test(groups = {"smoke"})
public void testLogin() {
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver");
WebDriver driver = new ChromeDriver();
try {
driver.get("http://staging.example.com");
new LoginPage(driver).login("demo", "demo123");
// Assertions here
} finally {
driver.quit();
}
}
}
2.5 Dockerfile – Java Webapp
# Stage 1 – Build
FROM eclipse-temurin:21-jdk AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# Stage 2 – Runtime
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /app/target/webapp-1.0.0.war /app/webapp.war
RUN apt-get update && apt-get install -y tomcat9
ENV CATALINA_HOME /usr/local/tomcat
COPY tomcat-config/* ${CATALINA_HOME}/conf/
CMD ["catalina.sh", "run"]
2.6 Deployment to Staging – Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: docker.io/myorg/webapp:123
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: staging
Edge Case – If the staging cluster has a network policy that restricts inbound traffic, you must expose the service with a LoadBalancer or Ingress.
2.7 Smoke Tests Post‑Deployment
Run a quick test that checks:
- Application is up (
curl -f http://staging.example.com). - Basic flows (login, create order).
- API health endpoint (
/actuator/health).
All smoke tests are grouped with @Test(groups = {"smoke"}) and executed by Jenkins.
2.8 Test Report Generation
- Allure – Generates interactive HTML.
- Jenkins –
publishJUnitResultsfor test results. - ExtentReports – Rich UI for visualizing test coverage.
Pro Tip – Keep the report artifacts in the workspace and archive them. This lets you compare builds.
3. Advanced Topics
3.1 Pipeline as Code Best Practices
| Practice | Why | How |
|---|---|---|
| Version Control | Trace changes | Commit Jenkinsfile in repo |
| Reusable Libraries | DRY | Jenkins Shared Libraries |
| Declarative over Scripted | Readability | Use pipeline {} syntax |
| Parameterization | Flexibility | parameters {} block |
| Branch‑specific Stages | CI for PRs | when { branch 'master' } |
| Caching | Speed | cache step for Maven/Gradle |
3.2 Parallel & Distributed Test Execution
stage('Run Tests') {
parallel {
stage('Chrome') {
steps { sh 'mvn test -Dbrowser=chrome' }
}
stage('Firefox') {
steps { sh 'mvn test -Dbrowser=firefox' }
}
}
}
- Use Selenium Grid or BrowserStack for cross‑browser.
- Leverage TestNG parallel execution (
parallel="methods").
3.3 Docker‑in‑Pipeline
- Build Docker image inside Jenkins using
docker.buildstep. - Use Docker Compose to spin up dependent services (DB, Redis).
stage('Integration Tests') {
steps {
sh """
docker-compose up -d
mvn verify -Ddocker
docker-compose down
"""
}
}
3.4 Canary & Blue/Green Deployment
| Method | How it works | When to use |
|---|---|---|
| Canary | Deploy new version to a subset of traffic. | When you need to monitor new release. |
| Blue/Green | Two identical environments, switch traffic. | When zero‑downtime is required. |
- In Jenkins, you can trigger a Blue/Green switch via a shell script that updates a
k8sservice selector.
3.5 Caching & Optimisation
| Tool | Use |
|---|---|
| Maven Dependency Caching | Cache ~/.m2/repository between builds. |
| Docker Layer Caching | Separate COPY of pom.xml and src/ to avoid rebuilding layers. |
| Parallel Stage Execution | Run tests and deployment in parallel if independent. |
| Gradle Build Cache | Use --build-cache for incremental builds. |
Pro Tip – Use Jenkins Pipeline Caching plugin to persist artifacts across stages.
3.6 Shared Libraries
Create a src/main/groovy/ directory in a separate repo. Import it in Jenkins:
@Library('my-shared-lib@master') _
pipeline {
agent any
stages {
stage('Deploy') {
steps {
deployToK8s('staging', 'webapp')
}
}
}
}
Industry Insight – Shared libraries reduce duplication across multiple projects and centralise best‑practice code.
3.7 Security & Compliance
- SonarQube – Static code analysis.
- OWASP Dependency‑Check – Detect vulnerable libraries.
- Snyk – Real‑time vulnerability scanning.
Add to pipeline:
stage('Static Analysis') {
steps {
sh 'mvn sonar:sonar'
}
}
4. Real‑World Applications
| Domain | Pipeline Highlights | Common Challenges |
|---|---|---|
| E‑commerce | High traffic, microservices, payment gateway. | Load testing, data isolation. |
| Banking | Regulatory compliance, security. | Secrets management, audit logs. |
| Microservices | Multiple services, inter‑service communication. | Service discovery, versioning. |
| Continuous Delivery | Frequent releases, feature flags. | Canary releases, rollback. |
Use‑Case Walk‑through: E‑commerce
- Checkout – Pull code, run unit tests.
- Build – Create Docker image.
- Deploy – Deploy to staging via Helm.
- Smoke – Verify cart, checkout flows.
- Performance – Run Gatling tests.
- Security – OWASP scan.
- Publish – Generate Allure reports.
5. Exercises
| # | Task | Learning Outcome |
|---|---|---|
| 1 | Create a Jenkinsfile that builds a Java project. | Understand pipeline syntax. |
| 2 | Add Selenium tests and run them in Jenkins. | Integrate test automation. |
| 3 | Build a Docker image inside Jenkins and push to Docker Hub. | Docker‑in‑pipeline. |
| 4 | Deploy the image to a local Minikube cluster. | Kubernetes deployment. |
| 5 | Implement smoke tests that verify the application after deployment. | Post‑deployment validation. |
| 6 | Generate Allure reports and archive them in Jenkins. | Reporting. |
| 7 | Optimize the pipeline by adding caching and parallel test stages. | Performance tuning. |
| 8 | Implement a Blue/Green deployment strategy in Jenkins. | Zero‑downtime deployments. |
| 9 | Add SonarQube analysis to the pipeline. | Static code analysis. |
| 10 | Create a Jenkins shared library that contains common deployment logic. | Reusability. |
Pro Tip – For each exercise, add a
README.mdthat documents the steps, issues encountered, and solutions.
Final Takeaway
- CI/CD is the backbone of modern Java automation testing.
- A well‑structured Jenkinsfile keeps builds reproducible and transparent.
- Integrating Selenium and JUnit/TestNG into the pipeline ensures early defect detection.
- Deploying to staging and running smoke tests validates that the deployment succeeded.
- Test reports (Allure, JUnit, Extent) provide visibility into test coverage and failures.
- Advanced techniques – parallel execution, Docker‑in‑pipeline, shared libraries, Blue/Green – elevate the pipeline to production‑grade.
Industry Insight – The most successful teams treat their CI/CD pipeline as a product that requires continuous improvement, monitoring, and security hardening.
Happy coding, and may your pipelines run smoothly!