Jenkins Pipeline Testing & Advanced Patterns

25 minLesson 8 of 8

Learning Objectives

  • Test pipelines locally with Jenkins Pipeline Unit
  • Implement advanced Groovy patterns
  • Build matrix builds for multi-platform testing
  • Design production-grade pipeline architectures

Testing Pipelines Locally

Jenkins Pipeline Unit Framework

// test/BuildPipelineTest.groovy
import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.Before
import org.junit.Test
 
class BuildPipelineTest extends BasePipelineTest {
    @Before
    void setUp() {
        super.setUp()
        helper.registerAllowedMethod('docker', [Map, Closure], null)
        helper.registerAllowedMethod('sh', [String], { cmd -> "mocked: ${cmd}" })
    }
 
    @Test
    void testBuildStage() {
        def script = loadScript('Jenkinsfile')
        script.execute()
        assertJobStatusSuccess()
    }
}

Linting Jenkinsfiles

# Use Jenkins CLI to validate syntax
curl -X POST -F "jenkinsfile=<Jenkinsfile" \
  https://jenkins.example.com/pipeline-model-converter/validate
 
# Or use npm package
npm install -g jenkinsfile-linter
jflint Jenkinsfile

Matrix Builds

Test across multiple platforms and versions simultaneously:

pipeline {
    agent none
    stages {
        stage('Test Matrix') {
            matrix {
                axes {
                    axis {
                        name 'NODE_VERSION'
                        values '18', '20', '22'
                    }
                    axis {
                        name 'OS'
                        values 'ubuntu-latest', 'alpine'
                    }
                }
                excludes {
                    exclude {
                        axis { name 'NODE_VERSION'; values '18' }
                        axis { name 'OS'; values 'alpine' }
                    }
                }
                stages {
                    stage('Test') {
                        agent { docker { image "node:${NODE_VERSION}-${OS}" } }
                        steps {
                            sh 'npm ci'
                            sh 'npm test'
                        }
                    }
                }
            }
        }
    }
}

Advanced Groovy Patterns

Dynamic Stage Generation

def services = ['api', 'web', 'worker', 'scheduler']
 
pipeline {
    agent any
    stages {
        stage('Build All Services') {
            steps {
                script {
                    def parallelStages = [:]
                    services.each { svc ->
                        parallelStages[svc] = {
                            stage("Build ${svc}") {
                                sh "docker build -t ${svc}:${BUILD_NUMBER} ./${svc}/"
                            }
                        }
                    }
                    parallel parallelStages
                }
            }
        }
    }
}

Conditional Pipeline Logic

pipeline {
    agent any
    stages {
        stage('Determine Deploy Target') {
            steps {
                script {
                    if (env.BRANCH_NAME == 'main') {
                        env.DEPLOY_ENV = 'production'
                        env.REPLICAS = '5'
                    } else if (env.BRANCH_NAME == 'develop') {
                        env.DEPLOY_ENV = 'staging'
                        env.REPLICAS = '2'
                    } else {
                        env.DEPLOY_ENV = 'preview'
                        env.REPLICAS = '1'
                    }
                }
            }
        }
        stage('Deploy') {
            steps {
                sh "deploy.sh --env ${DEPLOY_ENV} --replicas ${REPLICAS}"
            }
        }
    }
}

Production Pipeline Architecture

pipeline {
    agent none
    options {
        buildDiscarder(logRotator(numToKeepStr: '20'))
        timeout(time: 45, unit: 'MINUTES')
        timestamps()
        ansiColor('xterm')
    }
 
    environment {
        REGISTRY = 'registry.nextgenplayground.org'
        APP = 'nextgen-platform'
        TAG = "${BUILD_NUMBER}-${GIT_COMMIT[0..7]}"
    }
 
    stages {
        stage('Quality Gate') {
            parallel {
                stage('Lint') {
                    agent { docker { image 'node:20' } }
                    steps { sh 'npm ci && npm run lint' }
                }
                stage('Type Check') {
                    agent { docker { image 'node:20' } }
                    steps { sh 'npm ci && npm run typecheck' }
                }
                stage('Security Scan') {
                    agent { docker { image 'node:20' } }
                    steps { sh 'npm audit --audit-level=high' }
                }
            }
        }
 
        stage('Test') {
            agent { docker { image 'node:20' } }
            steps {
                sh 'npm ci && npm run test:ci'
            }
            post {
                always { junit 'reports/*.xml' }
            }
        }
 
        stage('Build & Push') {
            agent { label 'docker' }
            steps {
                sh "docker build -t ${REGISTRY}/${APP}:${TAG} ."
                withCredentials([usernamePassword(
                    credentialsId: 'registry',
                    usernameVariable: 'USER',
                    passwordVariable: 'PASS'
                )]) {
                    sh "echo $PASS | docker login ${REGISTRY} -u $USER --password-stdin"
                    sh "docker push ${REGISTRY}/${APP}:${TAG}"
                }
            }
        }
 
        stage('Deploy Staging') {
            when { branch 'main' }
            agent { label 'deploy' }
            steps {
                deployToK8s(env: 'staging', image: "${REGISTRY}/${APP}:${TAG}")
                sh 'run-smoke-tests.sh staging'
            }
        }
 
        stage('Deploy Production') {
            when { branch 'main' }
            input { message 'Deploy to production?' }
            agent { label 'deploy' }
            steps {
                deployToK8s(env: 'production', image: "${REGISTRY}/${APP}:${TAG}")
            }
        }
    }
 
    post {
        success { notifySlack(status: 'success') }
        failure { notifySlack(status: 'failure') }
        always { cleanWs() }
    }
}

Summary

You've learned:

  • Testing pipelines with Jenkins Pipeline Unit and linting
  • Matrix builds for multi-platform testing
  • Dynamic stage generation and advanced Groovy patterns
  • Production-grade pipeline architecture
  • Combining all Jenkins concepts into enterprise workflows

Next Steps

You now have a complete Jenkins CI/CD foundation. Combine with Kubernetes for deployment, Ansible for configuration, and Monitoring for observability.