Freestyle jobs are GUI toys. Real QA engineers use Pipeline jobs defined in a Jenkinsfile. This file lives in your Git repository alongside your test code. It is version-controlled, code-reviewed, and reproducible. If Jenkins explodes tomorrow, you create a new Pipeline job, point it to your repo, and everything is back in 2 minutes.
A Jenkinsfile uses Groovy-based DSL. Do not worry — you do not need to learn Groovy. It is a structured format. Think of it as a recipe card: ingredients on top, steps in order, cleanup instructions at the bottom.
pipeline {
// WHERE to run — any available agent/node
agent any
// TOOLS needed — must match names in Manage Jenkins > Tools
tools {
maven 'Maven-3.9'
jdk 'JDK-17'
}
// ENVIRONMENT VARIABLES — available to all stages
environment {
BASE_URL = 'https://www.testerrank.com'
REPORT_DIR = 'target/allure-results'
}
// THE PIPELINE — stages run top to bottom
stages {
stage('Checkout') {
steps {
// Pull code from the configured Git repo
checkout scm
}
}
stage('Build') {
steps {
// Compile without running tests — catch errors early
sh 'mvn clean compile -DskipTests'
}
}
stage('Run Tests') {
steps {
sh '''
mvn test \
-DsuiteXmlFile=testng.xml \
-Dbase.url=${BASE_URL} \
-Dheadless=true
'''
}
}
stage('Generate Report') {
steps {
allure([
results: [[path: 'target/allure-results']]
])
}
}
}
// WHAT HAPPENS AFTER — success, failure, or always
post {
success {
echo 'All tests passed!'
}
failure {
echo 'Tests failed. Check the Allure report.'
}
always {
// Publish TestNG results
testNG(reportFilenamePattern: '**/testng-results.xml')
// Archive reports
archiveArtifacts artifacts: 'target/surefire-reports/**',
allowEmptyArchive: true
// Clean workspace
cleanWs()
}
}
}| Block | Purpose | Example |
|---|---|---|
| pipeline {} | Root block — everything goes inside | Required, only one per file |
| agent any | Run on any available node | agent { label "linux" } for specific node |
| tools {} | Auto-install tools for this job | maven "Maven-3.9", jdk "JDK-17" |
| environment {} | Set env variables for all stages | BASE_URL = "https://www.testerrank.com" |
| stages {} | Container for all stages | Stages run sequentially by default |
| stage("Name") {} | One step in the pipeline | Checkout, Build, Test, Report |
| steps {} | Actual commands inside a stage | sh "mvn test", checkout scm |
| post {} | Actions after pipeline completes | success {}, failure {}, always {} |
| Declarative (Use This) | Scripted (Avoid for Now) |
|---|---|
| Starts with pipeline {} | Starts with node {} |
| Structured and easy to read | Full Groovy programming language |
| Built-in error handling with post {} | Manual try-catch for error handling |
| Industry standard for QA pipelines | Used for complex DevOps pipelines |
| Limited but sufficient for most needs | More flexible but harder to maintain |
Key Point: The Jenkinsfile lives in your Git repo. When Jenkins builds, it checks out the code and reads the Jenkinsfile from that commit. Different branches can have different Jenkinsfiles.
Indentation matters in Jenkinsfile. Use consistent 4-space indentation. A missing closing brace will give you a cryptic Groovy compilation error. Use a linter or the Pipeline Syntax tool in Jenkins (available at http://localhost:8080/pipeline-syntax).
Key Point: A Jenkinsfile is your pipeline as code — version-controlled, structured with stages, and stored in your Git repo.