Search code examples
jenkinsjenkins-pipelinejenkins-groovy

How can JenkinsPipelineUnit be used with shared declarative pipelines?


This is my test (copied from the snippets in the docs)

package vars

import org.junit.Before
import org.junit.Test
import com.lesfurets.jenkins.unit.declarative.*

class ExampleDeclarativePipelineTest extends DeclarativePipelineTest {
  // Setup environment for running unit tests
  @Override
  @Before
  public void setUp() throws Exception {
    super.setUp();
  }

  @Test
  public void should_execute_without_errors() throws Exception {
      //def script = runScript("vars/exampleDeclarativePipeline.groovy")
      def script = runScript("vars/Jenkinsfile")
      assertJobStatusSuccess()
      printCallStack()
  }
}

That works if I have an actual Jenkinsfile, but I defined my pipeline in my shared library (common pattern at this point) and it looks like this:

def call(Map config) {
    pipeline {
        agent none
        stages {
            stage('Example Build') {
                agent { docker 'maven:3-alpine' }
                steps {
                    echo 'Hello, Maven'
                    sh 'mvn --version'
                }
            }
            stage('Example Test') {
                agent { docker 'openjdk:8-jre' }
                steps {
                    echo 'Hello, JDK'
                    echo 'Hello, JDK'
                    echo 'Hello, JDK'
                    echo 'Hello, JDK'
                    echo 'Hello, JDK'
                    sh 'java -version'
                }
            }
        }
    }
}

If I point my test to this Groovy script (def script = runScript("vars/exampleDeclarativePipeline.groovy")) it seems to do nothing. It executes but I don't get a stack trace or anything (if it's a standard Jenkinsfile it works).

How can I test my shared pipeline code?

Wasn't sure if this was a bug so I opened one: https://github.com/jenkinsci/JenkinsPipelineUnit/issues/380


Solution

  • I experienced the same issue/roadblock; the 'solution' I used is to create a Jenkinsfile (per var in vars) and include my library as a 'Shared Library' via helper.registerSharedLibrary() (ProjectSource). Example-code based on my workaround:

    File structure:

    project_root
    ├── test
    |    ├── vars
    |    |    └── test-jenkinsfile.groovy
    |    └── TestSpec.groovy
    ├── vars
    |    └── test.groovy
    ...
    

    test.groovy:

    def call(stuff) {
        pipelines {
            agent none
            stages('hello') {
                stage {
                    echo 'world'
                }
            }
        }
    }
    

    TestSpec.groovy:

    ...
    class TestSpec extends DeclarativePipelineTest {
        @Override
        @Before
        void setUp() throws Exception {
            // Set dir info
            baseScriptRoot = ''
            scriptRoots = ['test/vars/']
            scriptExtension = 'groovy'
            
            
            super.setUp()
    
            // load own shared library
            def library = LibraryConfiguration.library().name('hello-world')
                            .defaultVersion('<notNeeded>')
                            .allowOverride(true)
                            .implicit(true)
                            .targetPath('<notNeeded>')
                            .retriever(ProjectSource.projectSource())
                            .build()
            helper.registerSharedLibrary(library)
    
            ...
        }
    
        @Test
        void runHelloWorldPipeline() {
            runScript('test-jenkinsfile.groovy')
            printCallStack()
            assertJobStatusSuccess()
        }
    }
    

    test-jenkinsfile.groovy:

    ...
    @Library('hello-world')  _
    test {}
    

    Warning: I just started (8h ago) down this route and it seems to be working, for me and for now.