Git Product home page Git Product logo

pipelineunit's Introduction

pipelineUnit

This project demonstrates how to write unit tests for Jenkins pipeline code including declarative pipelines, scripted pipelines and shared library code under the /vars area. The framework does not strictly validate the pipeline syntax but it will emulate the pipeline using the JenkinsPipelineUnit framework and can validate any groovy script sections in the pipeline and logic. It may not be complete for all pipeline syntax.

It is using Spock, Gradle and Groovy and the JenkinsPipelineUnit framework available here: https://github.com/lesfurets/JenkinsPipelineUnit

The unit test is actually testing the Jenkinsfile that builds this Gradle project on Jenkins.

The below is an example of a unit test output from Jenkins console:

tests.job.JenkinsfileTestSpec > Jenkinsfile should run gradle tests with expected command line STANDARD_OUT
    post failure skipped as not FAILURE
    post unstable skipped as SUCCESS
    >>>>>> pipeline call stack -------------------------------------------------
       Jenkinsfile.run()
          Jenkinsfile.pipeline(groovy.lang.Closure)
             Jenkinsfile.agent(groovy.lang.Closure)
             Jenkinsfile.options(groovy.lang.Closure)
                Jenkinsfile.logRotator({numToKeepStr=10})
                Jenkinsfile.buildDiscarder(null)
                Jenkinsfile.timestamps()
             Jenkinsfile.triggers(groovy.lang.Closure)
                Jenkinsfile.pollSCM(*/5 * * * *)
             Jenkinsfile.stages(groovy.lang.Closure)
                Jenkinsfile.stage(Checkout, groovy.lang.Closure)
                   Jenkinsfile.steps(groovy.lang.Closure)
                      Jenkinsfile.deleteDir()
                      Jenkinsfile.checkout(groovy.lang.Closure)
                Jenkinsfile.stage(build, groovy.lang.Closure)
                   Jenkinsfile.steps(groovy.lang.Closure)
                      Jenkinsfile.tool({name=GRADLE_3, type=hudson.plugins.gradle.GradleInstallation})
                      Jenkinsfile.withEnv([GRADLE_HOME=GRADLE_3_HOME], groovy.lang.Closure)
                         Jenkinsfile.withEnv([PATH=/some/path:GRADLE_3_HOME/bin], groovy.lang.Closure)
                            Jenkinsfile.echo(GRADLE_HOME=GRADLE_3_HOME)
                            Jenkinsfile.echo(PATH=/some/path:GRADLE_3_HOME/bin)
                            Jenkinsfile.sh(gradle clean build test -i)
                Jenkinsfile.stage(validate, groovy.lang.Closure)
                   Jenkinsfile.steps(groovy.lang.Closure)
                      Jenkinsfile.echo(TODO: syntactic validation of Jenkinsfiles)
             Jenkinsfile.post(groovy.lang.Closure)
                Jenkinsfile.always(groovy.lang.Closure)
                   Jenkinsfile.echo(pipeline unit tests completed)
                Jenkinsfile.success(groovy.lang.Closure)
                   Jenkinsfile.echo(pipeline unit tests PASSED)
                Jenkinsfile.failure(groovy.lang.Closure)
                Jenkinsfile.changed(groovy.lang.Closure)
                   Jenkinsfile.echo(pipeline unit tests results have CHANGED)
                Jenkinsfile.unstable(groovy.lang.Closure)
       Jenkinsfile.execute()

pipelineunit's People

Contributors

fstaats avatar macg33zr avatar steveprentice avatar szpak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pipelineunit's Issues

Move PipelineTestHelper to static field.

Recent versions of the PipelineUnitTests (1.2+) moved the PipelineTestHelper to a Singleton class. PipelineSpockTestBase currently instantiates a new instance each time a test is run, which seems wasteful.

I have added a static field to store the singleton instance, and just run setUp() on in the setup() method. This reduced my test time from ~5 minutes to ~20 seconds (for 165 tests).

class PipelineSpockTestBase extends Specification implements RegressionTest {

    /**
     * Delegate to the test helper
     */
    @Delegate PipelineTestHelper pipelineTestHelper

    static internalPipelineHelper = new PipelineTestHelper()
    /**
     * Do the common setup
     */
    def setup() {

        // Set callstacks path for RegressionTest
        callStackPath = 'pipelineTests/groovy/tests/callstacks/'

        // Create and config the helper
        pipelineTestHelper = internalPipelineHelper
        pipelineTestHelper.setUp()
    }
}

tests.job.CIPipelineTest > validate shell command[0] FAILED

sorry i am a noob with this frameowrk, any help in identifying the below issue is appreciated!

Unit Test cases fail with below error when three double quotes are used along with sh in Jenkinsfile

problem is when i use three double quotes without which i cannot get the value of groovy variable

Jenkinsfile Stage

stage('duration') {
steps{
withCredentials([string(credentialsId: 'GH_TOKEN', variable: 'GH_TOKEN'), usernamePassword(credentialsId: '', passwordVariable: 'dbpassword', usernameVariable: 'dbuser')]) {
script {
currentBuild.displayName = "$ghprbPullId"
sh """
echo ${currentBuild.durationString.replace(' and counting', '')} > duration.txt
cat duration.txt
"""
}
}
}
}

Error from Unit test case

tests.job.CIPipelineTest > validate the pipeline FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:18

tests.job.CIPipelineTest > validate shell command[0] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[1] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[2] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[3] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[4] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[5] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[6] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[7] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[8] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

tests.job.CIPipelineTest > validate shell command[9] FAILED
org.codehaus.groovy.control.MultipleCompilationErrorsException at CIPipelineTest.groovy:34

11 tests completed, 11 failed
:test FAILED

Error when testing pipeline library file with named parameters

Error when testing pipeline library file that has more than one parameters:

err:

groovy.lang.MissingMethodException: No signature of method: addPolicy.call() is applicable for argument types: (tests.library.runAddPolicySpec$__spock_feature_1_0_closure1) values: [tests.library.runAddPolicySpec$__spock_feature_1_0_closure1@17a6c499]
Possible solutions: wait(), any(), wait(long), call(java.lang.String, java.lang.String, java.lang.String, java.lang.String), main([Ljava.lang.String;), each(groovy.lang.Closure)
	at com.lesfurets.jenkins.unit.PipelineTestHelper$_closure4.doCall(PipelineTestHelper.groovy:182)
	at com.lesfurets.jenkins.unit.PipelineTestHelper$_closure3.doCall(PipelineTestHelper.groovy:143)
	at tests.library.runAddPolicySpec.test myshared library code(TestAddPolicy.groovy:25)

vars/addPolicy.groovy:

def call(String bucketName, String arnToAdd, String profile, String region) {
  ...
}

test:

class runAddPolicySpec extends PipelineSpockTestBase {

    def "test myshared library code"() {

        given:
        def paramsPassed = {
            bucketName= "..."
            arnToAdd= "..." 
            profile="..."
            region="..."
        }
        callStackPath = 'src'

        when:
        def script = loadScript('vars/addPolicy.groovy')
        script.call(paramsPassed)

        then:
        printCallStack()
        assertJobStatusSuccess()
    }
}

...while the given example test with one parameter works:
exampleJob.jenkins with body def call(body) {

Is this a bug or i should do something differently?

Put Code into MavenCentral?

Hi @macg33zr,

i do really appreciate your work done here! I saw the code, mostly under testsupport copy'd into several projects. Have you thought about putting it into maven central?

Regards, Max

When the Jenkinsfile is renamed and the path in the test is adjusted the test fails

When Jenkinsfile was renamed, e.g. x.jenkins and the path in the test as well, the gradle build fails:

when cloned:

gradle clean build

BUILD SUCCESSFUL in 8s
4 actionable tasks: 4 executed

when Jenkinsfile renamed

gradle clean build

> Task :test 

tests.job.JenkinsfileTestSpec > Jenkinsfile should run gradle tests with expected command line validate:null gradle: null FAILED
    groovy.util.ResourceException at JenkinsfileTestSpec.groovy:26
        Caused by: groovy.util.ResourceException at JenkinsfileTestSpec.groovy:26

Then I thought perhaps there is another jenkins file. This was the case, i.e. ./exampleJobs/parallel/Jenkinsfile and when this was renamed the issue persisted.

Should all Jenkins. entries that reside in the test files be renamed as well?

How to mock variables/methods which are added in src packages

I have a common code in src folder, in package com.mycom.utils File : CommonStages.groovy Code:

    package com.mycom.utils
    def execute() {
      stage('some stage') {
        node ('someNode'){
          Println env.someenv
          
          }
         }
        }

Am getting no signature of method error com.mycom.utils.commonstages.stage() Is applicable for argument types: (java.lang.String, com.mycom.utils.commonsatges$_execute_closure1)

If the code is in jenkinsfile it executes but when I add it to the package structure it fails

test case using spock:

        def "common pipeline"() {
        given:
       

    when:

          helper.registerAllowedMethod('node', [Closure.class], null)
         helper.registerAllowedMethod("stage", [String.class], null)

         addEnvVar('PIPELINE_TYPE', 'PIPELINE_TYPE')
         def script = loadScript('Jenkinsfile')
        then:
        printCallStack()
      }

How to use pipelineUnit?

Hello, I'm familiar with the javascript/python ecosystem but I know almost nothing about the java ecosystem. I've been trying to learn how to use this use pipelineUnit but I can't figure it out.

I gather that I need to be familiar with

  • Graddle
  • JUnit
  • Java
  • Groovy
  • Jenkinsfile

Is there anything else I should be familiar with before being able to use this package?

withEnv variable values that contain '=' cause an assertion failure

helper.registerAllowedMethod('withEnv', [List.class, Closure.class], { List list, Closure c ->
list.each {
//def env = helper.get
def item = it.split('=')
assert item.size() == 2, "withEnv list does not look right: ${list.toString()}"
addEnvVar(item[0], item[1])
c.delegate = binding
c.call()
}
})

If I'm using a withEnv block in my Jenkinsfile and the value of my variable contains an equals symbol (which is often the case when setting JVM options for example) then Pipeline Unit is unable to add the environment variables correctly.

Eg.
withEnv(['JVM_OPTS="-Dhttps.proxyHost=some.host"'])

pipelineUnit example does not work with com.lesfurets:jenkins-pipeline-unit:1.1

I need some of the new features in JenkinsPipelineUnit 1.1 (e.g. Windows build support). When using JenkinsPipelineUnit 0.12 your example works. When I tried upgrading your example here by changing the dependency to "com.lesfurets:jenkins-pipeline-unit:1.1" I get errors like the following. I don't know spock well enough to debug what has changed. Do you have any ideas?

Too few invocations for:

1 * shellMock.call(_) >> { args ->

            def shellCmd = args[0]
            assert shellCmd == GRADLE_EXPECTED_CMD
        }   (0 invocations)

Unmatched invocations (ordered by similarity):

None


Too few invocations for:

1 * shellMock.call(_) >> { args ->

            def shellCmd = args[0]
            assert shellCmd == GRADLE_EXPECTED_CMD
        }   (0 invocations)

Unmatched invocations (ordered by similarity):

None

	at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:78)
	at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:76)
	at tests.job.JenkinsfileTestSpec.Jenkinsfile should run gradle tests with expected command line validate:#P_VALIDATE gradle: #P_GRADLE_TASKS_OPTIONS(JenkinsfileTestSpec.groovy:24)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.