Jenkins is one of the most established automation servers for Continuous Integration and Continuous Delivery. For QA engineers, its real value is not simply “running tests on a server”: Jenkins can turn source-code changes into repeatable build, test, reporting and notification workflows that execute consistently across teams and environments. This guide covers Jenkins from CI/CD fundamentals through installation, first jobs, automated test execution, Maven and GitHub integration, parallel and parameterised pipelines, selective test execution, reports and email notifications.
Continuous Integration and Continuous Delivery
Continuous Integration (CI) is the practice of integrating code changes frequently and validating them automatically. Every relevant change should trigger a repeatable process that builds the software and provides fast feedback about quality.
Continuous Delivery (CD) extends that automation so a validated build remains releasable. Continuous Deployment goes further and releases qualifying changes automatically.
| Practice | Main objective | Typical automation |
|---|---|---|
| Continuous Integration | Detect integration problems quickly. | Build, unit tests, static analysis, API tests, critical UI smoke. |
| Continuous Delivery | Keep validated software ready to release. | Packaging, environment deployment, broader validation and release gates. |
| Continuous Deployment | Release every qualifying change automatically. | Production deployment, smoke validation, monitoring and rollback. |
Developer change
↓
Git push / Pull Request
↓
Jenkins triggered
↓
Checkout
↓
Build
↓
Automated tests
↓
Reports
↓
Pass / Fail feedback
↓
Merge or fix
Why CI matters to QA
Early feedback
Regression is detected closer to the change that introduced it.
Repeatability
The same commands and environment rules are applied consistently.
Visibility
Developers, QA and product teams share build and test status.
Traceability
Results can be linked to commits, branches and pipeline executions.
Quality gates
Critical failures can stop later delivery stages automatically.
Scale
Suites can run across agents, browsers and environments in parallel.
Choose the right tests for each pipeline moment
| Pipeline moment | Good candidates |
|---|---|
| Every push / PR | Build, lint, unit tests, component tests, API smoke and critical UI smoke. |
| Merge to main | Broader API/integration coverage and selected end-to-end regression. |
| Nightly | Full regression, cross-browser suites and longer-running checks. |
| Pre-release | Release regression, performance, security and deployment validation. |
Introduction to Jenkins
Jenkins is an open-source automation server that can orchestrate build and delivery workflows, execute commands on distributed workers, integrate with source control and publish status, reports and notifications.
Common QA uses
- Build after a push.
- Run tests for pull requests.
- Schedule nightly regression.
- Execute tests on different operating systems or browsers.
- Publish JUnit and HTML reports.
- Archive screenshots, traces and logs.
- Notify the team when validation fails or recovers.
Freestyle vs Pipeline
| Freestyle | Pipeline |
|---|---|
| Configured mostly through the Jenkins UI. | Defined as code, normally in a Jenkinsfile. |
| Easy for a first experiment. | Better for real CI/CD workflows. |
| Harder to review configuration in Git. | Pipeline changes can be code-reviewed. |
| Less convenient for complex logic. | Supports stages, conditions, parallelism and matrices. |
Jenkinsfile.How Jenkins works
┌─────────────────────┐
│ Jenkins Controller │
GitHub webhook ───▶ │ Queue / Scheduling │
│ Pipeline state │
│ UI / Configuration │
└──────────┬──────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
Linux Agent Windows Agent Docker Agent
Build/Test Browser/Test Build/Test
The controller coordinates Jenkins, stores configuration, schedules work and monitors agents. Agents provide executors that perform Pipeline work.
0 and doing build/test work on agents.Core Pipeline concepts
| Concept | Meaning |
|---|---|
| Pipeline | The complete automated workflow. |
| Agent | The machine or environment where work executes. |
| Stage | A meaningful workflow section such as Build or Test. |
| Step | An individual action inside a stage. |
| Workspace | The directory used by a job on an agent. |
| Artefact | A file preserved from the run such as a package, screenshot or log. |
Jenkins installation and configuration
Jenkins can be installed using native packages, a WAR file, Docker or Kubernetes. At the time of writing in August 2026, the Jenkins site lists 2.568.2 as the current LTS release and the current LTS line uses modern Java runtimes such as Java 21 or 25.
| Method | Good for |
|---|---|
| Docker | Repeatable local/team setup and infrastructure automation. |
| Linux package | Traditional long-running server installations. |
| Windows installer | Windows-based environments. |
| WAR file | Quick standalone evaluation. |
| Kubernetes | Cloud-native Jenkins and dynamic agents. |
Local WAR example
java -jar jenkins.war --httpPort=8080
Initial configuration checklist
- Create the administrator account.
- Install only required plugins.
- Configure the Jenkins URL.
- Configure agents.
- Add source-control credentials through Jenkins Credentials.
- Configure JDK/Maven tools if using managed installations.
- Configure SMTP if email is required.
- Apply appropriate permissions.
- Plan backup and recovery.
Plugin hygiene
- Keep the plugin set minimal.
- Track security advisories.
- Test Jenkins/plugin upgrades before production rollout.
- Remove unused plugins.
- Prefer native Pipeline features when possible.
- Keep Jenkins on a supported LTS release.
Creating the first Jenkins job
- From the dashboard select New Item.
- Choose Freestyle project.
- Add Source Code Management if needed.
- Add an Execute shell build step.
- Save and select Build Now.
- Review Console Output.
echo "Running on $NODE_NAME"
java -version
git --version
Your first Jenkins Pipeline
Create a Jenkinsfile in the repository root:
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building application'
}
}
stage('Test') {
steps {
echo 'Running automated tests'
}
}
}
}
Create a Jenkins Pipeline item and configure it to load the Pipeline script from SCM.
Test automation integration prerequisites
Jenkins should run the same commands that already work locally. Before CI integration:
- Tests run non-interactively from the command line.
- Dependencies install without manual UI steps.
- Environment-specific values come from configuration.
- Secrets are not stored in the repository.
- Failures return non-zero exit codes.
- Tests can produce machine-readable reports.
- Test data and environment dependencies are documented.
- Browser tests support headless execution where appropriate.
# Maven
mvn test
# Playwright
npx playwright test
# Cypress
npx cypress run
# pytest
pytest
# Robot Framework
robot tests/
Continuous Integration for automated test execution
pipeline {
agent { label 'qa-linux' }
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Dependencies') {
steps {
sh 'npm ci'
}
}
stage('Tests') {
steps {
sh 'npm test'
}
}
}
}
By default, a shell command that exits non-zero causes the stage to fail. This makes the test runner's process exit code part of the CI contract.
Maven integration with Jenkins
For Java projects, Maven can be available directly on the agent, configured under Manage Jenkins → Tools, provided through Docker or configured with the Pipeline Maven Integration plugin.
pipeline {
agent any
tools {
maven 'Maven-3.9'
jdk 'JDK-21'
}
stages {
stage('Build and Test') {
steps {
sh 'mvn -B clean verify'
}
}
}
}
| Command | Typical use |
|---|---|
mvn test | Compile and run tests. |
mvn clean test | Clean previous output and run tests. |
mvn verify | Run lifecycle checks through verify. |
mvn clean verify | Common clean CI verification command. |
Maven with Docker
pipeline {
agent {
docker {
image 'maven:3.9.9-eclipse-temurin-21'
}
}
stages {
stage('Verify') {
steps {
sh 'mvn -B clean verify'
}
}
}
}
Pipeline Maven Integration plugin
pipeline {
agent any
stages {
stage('Test') {
steps {
withMaven(maven: 'Maven-3.9') {
sh 'mvn -B clean verify'
}
}
}
}
}
Jenkins integration with GitHub
GitHub integration normally has two responsibilities: Jenkins checks out source code from GitHub, and GitHub events notify Jenkins when a build should start.
Developer pushes commit
↓
GitHub
↓
Webhook POST
↓
Jenkins
↓
SCM checkout
↓
Pipeline execution
↓
Status / reports
The Jenkins GitHub plugin can receive push webhooks. A typical endpoint is:
https://jenkins.example.com/github-webhook/
Prefer webhooks over frequent SCM polling when the network architecture allows GitHub to reach Jenkins.
GitHub credentials
Never hard-code repository credentials or tokens in a Jenkinsfile. Store credentials in Jenkins and reference them by credential ID.
- Use least-privilege credentials.
- Prefer narrowly scoped or short-lived credentials where possible.
- Restrict which jobs can access sensitive credentials.
- Avoid leaking credentials through command interpolation or logs.
- Rotate credentials periodically.
Multibranch Pipeline for branches and pull requests
A Multibranch Pipeline automatically discovers branches containing a Jenkinsfile and manages their Pipelines. This is normally more scalable than manually creating a Jenkins job per feature branch.
- Validate each branch automatically.
- Support pull-request workflows.
- Version Pipeline configuration with branch code.
- Reduce manual Jenkins job maintenance.
- Allow branch-specific Pipeline evolution.
Parallel test execution
Parallel execution can reduce feedback time dramatically, but only when the tests and environment are safe to run concurrently.
pipeline {
agent none
stages {
stage('Regression') {
parallel {
stage('API') {
agent { label 'linux' }
steps {
sh 'npm run test:api'
}
}
stage('Chrome') {
agent { label 'chrome' }
steps {
sh 'npm run test:chrome'
}
}
stage('Firefox') {
agent { label 'firefox' }
steps {
sh 'npm run test:firefox'
}
}
}
}
}
}
Fail fast
stage('Parallel Tests') {
failFast true
parallel {
stage('Suite A') {
steps {
sh 'npm run test:a'
}
}
stage('Suite B') {
steps {
sh 'npm run test:b'
}
}
}
}
Cross-browser and cross-platform Matrix
Declarative Pipeline supports a matrix for repeated test stages across combinations such as browsers and environments.
pipeline {
agent none
stages {
stage('Cross Browser') {
matrix {
axes {
axis {
name 'BROWSER'
values 'chrome', 'firefox'
}
axis {
name 'ENVIRONMENT'
values 'qa', 'staging'
}
}
agent { label 'ui-test' }
stages {
stage('Test') {
steps {
sh "npm run test:e2e -- --browser=${BROWSER} --env=${ENVIRONMENT}"
}
}
}
}
}
}
}
Parallel test prerequisites
- Tests do not share mutable user accounts unless designed for it.
- Test data is isolated.
- Agents have sufficient CPU and memory.
- Reports use unique output paths.
- Ports and temporary resources do not collide.
- The target environment can handle the extra load.
- Tests can run independently.
How to ignore or skip tests from Jenkins
“Skip tests” can mean several different things. Choose the narrowest approach that matches the actual requirement.
Conditionally skip a Pipeline stage
parameters {
booleanParam(
name: 'RUN_E2E',
defaultValue: true,
description: 'Run end-to-end tests'
)
}
stage('E2E') {
when {
expression { params.RUN_E2E }
}
steps {
sh 'npm run test:e2e'
}
}
Run only a tagged subset
# Maven / framework-dependent
mvn test -Dgroups=smoke
# Cypress
npx cypress run --spec "cypress/e2e/smoke/**"
# Playwright
npx playwright test --grep @smoke
Skip Maven test execution
mvn -DskipTests package
Skip Maven test compilation and execution
mvn -Dmaven.test.skip=true package
Use conditions instead of duplicating jobs
stage('Full Regression') {
when {
anyOf {
branch 'main'
expression { params.RUN_FULL_REGRESSION }
}
}
steps {
sh 'npm run test:regression'
}
}
One versioned Pipeline with explicit conditions is normally easier to maintain than multiple nearly identical jobs.
Parameterized Jenkins jobs
Parameters make one Pipeline reusable for different environments, suites or runtime options without editing the Jenkinsfile.
pipeline {
agent any
parameters {
choice(
name: 'ENVIRONMENT',
choices: ['qa', 'staging'],
description: 'Target environment'
)
choice(
name: 'SUITE',
choices: ['smoke', 'regression'],
description: 'Test suite'
)
booleanParam(
name: 'HEADLESS',
defaultValue: true,
description: 'Run browser headless'
)
}
stages {
stage('Test') {
steps {
sh """
npm run test:${params.SUITE} -- \
--env=${params.ENVIRONMENT} \
--headless=${params.HEADLESS}
"""
}
}
}
}
Good parameters
Use parameters for intentional runtime choices such as environment, suite, browser or optional diagnostics.
Bad parameters
Do not use ordinary build parameters to expose secrets, bypass important controls casually or create undocumented combinations that nobody can support.
Report generation through Jenkins
A test run is much more useful when Jenkins understands the results instead of storing only console text.
Publish JUnit XML
post {
always {
junit testResults: 'test-results/**/*.xml',
allowEmptyResults: true
}
}
Jenkins can use JUnit-format XML to show historical trends and individual failures. Many non-Java frameworks can generate this format too.
Publish HTML reports
post {
always {
publishHTML(target: [
reportDir: 'reports',
reportFiles: 'index.html',
reportName: 'Automation Report',
keepAll: true,
alwaysLinkToLastBuild: true,
allowMissing: false
])
}
}
Archive raw evidence
post {
always {
archiveArtifacts(
artifacts: 'test-results/**/*, screenshots/**/*, traces/**/*',
allowEmptyArchive: true
)
}
}
| Output | Purpose |
|---|---|
| JUnit XML | Structured pass/fail history inside Jenkins. |
| HTML report | Human-readable test detail. |
| Screenshots/video/trace | Failure diagnosis. |
| Console output | Pipeline and command execution. |
| JSON/raw data | Custom metrics or later analysis. |
Sending emails from Jenkins
Jenkins supports a simple mail Pipeline step. The Email Extension plugin adds the richer emailext step.
Simple failure email
post {
failure {
mail(
to: 'qa-team@example.com',
subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
Job: ${env.JOB_NAME}
Build: ${env.BUILD_NUMBER}
URL: ${env.BUILD_URL}
"""
)
}
}
Extended HTML email
post {
failure {
emailext(
to: 'qa-team@example.com',
subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
Automation failed
Job: ${env.JOB_NAME}
Build: ${env.BUILD_NUMBER}
""",
mimeType: 'text/html',
attachLog: true
)
}
}
Avoid notification fatigue
- Notify immediately on important failure.
- Notify when a previously failing Pipeline recovers.
- Use dashboards or chat integrations for routine status.
- Use summaries for broad scheduled regression where appropriate.
A complete Maven QA Jenkinsfile
pipeline {
agent { label 'linux' }
tools {
maven 'Maven-3.9'
jdk 'JDK-21'
}
options {
timestamps()
timeout(time: 45, unit: 'MINUTES')
disableConcurrentBuilds()
}
parameters {
choice(
name: 'SUITE',
choices: ['smoke', 'regression'],
description: 'Test suite'
)
choice(
name: 'ENVIRONMENT',
choices: ['qa', 'staging'],
description: 'Target environment'
)
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn -B clean compile'
}
}
stage('Test') {
steps {
sh """
mvn -B test \
-Dsuite=${params.SUITE} \
-Denvironment=${params.ENVIRONMENT}
"""
}
}
}
post {
always {
junit(
testResults: 'target/surefire-reports/*.xml',
allowEmptyResults: true
)
archiveArtifacts(
artifacts: 'target/**/*report*, target/screenshots/**/*',
allowEmptyArchive: true
)
}
failure {
mail(
to: 'qa-team@example.com',
subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "See ${env.BUILD_URL}"
)
}
}
}
Credentials and secrets
Secrets belong in Jenkins Credentials and should be injected only where required.
Never hard-code a secret
environment {
API_TOKEN = 'real-production-token'
}
Use a credential binding
steps {
withCredentials([
string(credentialsId: 'qa-api-token', variable: 'API_TOKEN')
]) {
sh './run-api-tests.sh'
}
}
- Do not echo secrets.
- Separate QA and production credentials.
- Grant credentials only to jobs that require them.
- Avoid exposing secrets in command-line arguments or logs.
CI stability practices
- Use timeouts so hung builds terminate.
- Use retries for infrastructure operations cautiously, not to hide flaky tests.
- Keep workspaces clean enough that one run does not depend on another.
- Use repeatable environments such as containers or ephemeral agents where practical.
- Publish diagnostics even when the test stage fails.
Timeout example
options {
timeout(time: 30, unit: 'MINUTES')
}
Handling flaky tests
| Bad response | Better response |
|---|---|
| Retry the full suite until green. | Capture the flaky test, investigate and track it. |
| Ignore the failing test forever. | Quarantine temporarily with owner and expiry. |
| Increase fixed sleeps. | Use deterministic waits and improve testability. |
| Hide unstable results. | Publish and measure instability. |
Quality gates
Build
↓
Unit tests
↓
API smoke
↓
UI smoke
↓
Static / security checks
↓
Package
↓
Deploy to QA
↓
Regression
↓
Release decision
Which stages block delivery depends on product risk, but the policy should be explicit and consistently enforced.
Scheduled regression
triggers {
cron('H 2 * * *')
}
This is useful for nightly or scheduled suites that should not execute on every source change.
Webhook vs polling
| Webhook | SCM polling |
|---|---|
| GitHub actively informs Jenkins. | Jenkins periodically checks source control. |
| Usually faster feedback. | Can create unnecessary polling traffic. |
| Preferred when connectivity allows it. | Useful when webhooks cannot reach Jenkins. |
Common Jenkins mistakes
| Mistake | Better approach |
|---|---|
| Everything configured manually in UI | Move project workflow to a Jenkinsfile. |
| Builds run on controller | Use dedicated agents. |
| Secrets committed to Jenkinsfile | Use Jenkins Credentials. |
| One giant test stage | Separate fast checks, smoke and regression. |
| Reports only in console text | Publish structured results and artefacts. |
| Polling constantly | Use GitHub webhooks where possible. |
| Full regression for every tiny change | Use risk-based suites and scheduled coverage. |
| Unlimited plugins | Keep a minimal maintained plugin set. |
| Every success emails everyone | Notify meaningful failures and recovery. |
Debugging Jenkins test failures
- Identify whether the Jenkins infrastructure or the test command failed.
- Compare CI and local versions, environment variables, paths, timezone and resources.
- Inspect reports, screenshots, traces and console output.
- Reproduce using the same command as Jenkins.
- Fix the root cause rather than adding CI-only workarounds.
Jenkins Pipeline checklist for QA
- Jenkins uses a supported LTS release and Java runtime.
- The controller is not the normal build executor.
- Build/test execution runs on labelled agents.
- The project has a version-controlled Jenkinsfile.
- Tests run reliably from the command line before Jenkins integration.
- Dependencies install non-interactively.
- Secrets use Jenkins Credentials.
- GitHub webhooks trigger relevant builds where possible.
- Multibranch Pipeline is considered for branch and PR validation.
- PR Pipelines focus on fast, high-value feedback.
- Full regression has an appropriate scheduled or release trigger.
- Parallel suites have isolated test data.
- Pipeline parameters are limited to intentional runtime choices.
- Skipping tests is exceptional and visible.
- JUnit-compatible results are published.
- HTML reports are published when useful.
- Screenshots, traces and logs are archived.
- Timeouts prevent hung builds.
- Flaky tests are measured and addressed.
- Email notifications are actionable rather than noisy.
- Pipeline changes receive code review.
- Plugin count is controlled and plugins are kept updated.
Jenkins cheat sheet
| Need | Example |
|---|---|
| Run Maven tests | mvn -B test |
| Clean verification | mvn -B clean verify |
| Skip test execution | mvn -DskipTests package |
| Pipeline parameter | params.ENVIRONMENT |
| Current build URL | env.BUILD_URL |
| Checkout SCM revision | checkout scm |
| Shell command | sh 'npm test' |
| Windows command | bat 'mvn test' |
| JUnit results | junit 'results/**/*.xml' |
| Archive files | archiveArtifacts artifacts: 'results/**/*' |
| Simple email | mail(...) |
| Extended email | emailext(...) |
Key takeaways
- CI is a feedback system, not merely a remote test runner.
- Pipeline as Code should be the default for maintainable Jenkins automation.
- The controller orchestrates while agents execute builds and tests.
- Tests should already work from the command line before Jenkins integration.
- Maven can be provided through Jenkins tools, containers or Pipeline integration.
- GitHub webhooks and Multibranch Pipeline scale branch and pull-request workflows.
- Parallel stages and matrices reduce feedback time when test isolation is sound.
- Parameterized jobs provide controlled runtime choices without duplicating Pipelines.
- Test skipping should be explicit and exceptional.
- Reports, artefacts and useful notifications turn CI executions into actionable QA evidence.
Useful links
- Jenkins Pipeline ↗ — official Pipeline guide.
- Using a Jenkinsfile ↗ — Pipeline as Code, credentials, parameters and parallel execution.
- Installing Jenkins ↗ — official installation options.
- Using Jenkins Agents ↗ — controller/agent architecture.
- Pipeline Syntax ↗ — parameters, conditions, parallel and matrix syntax.
- Jenkins GitHub Plugin ↗ — GitHub webhook integration.
- JUnit Pipeline Step ↗ — structured test results.
- HTML Publisher ↗ — generated HTML reports.
- Email Extension ↗ — richer email notifications.