skip to Main Content

currently i try to create a project to centralize the generation of job on my jenkins : i use jenkins job dsl 1.77 and try to follow this explanation : https://github.com/jenkinsci/job-dsl-plugin/wiki/Testing-DSL-Scripts

my env is : gradle 8 and jdk 11 on unix env (ubuntu)

here i follow the code :

// build.gradle
plugins {
    id 'groovy'
}

sourceSets {
    jobs {
        groovy {
            srcDirs 'src/jobs'
            compileClasspath += main.compileClasspath
        }
        compileClasspath += sourceSets.main.output
        runtimeClasspath += sourceSets.main.output
    }
    src {
        groovy {
            srcDir 'src/main/groovy'
        }
    }
    test {
        groovy {
            srcDir 'src/test/groovy'
        }
    }
}

repositories {
    mavenCentral()
    maven { url 'https://repo.jenkins-ci.org/releases/' }
    jcenter{url "https://jcenter.bintray.com/"}
}

configurations {
    testPlugins {}

    // see JENKINS-45512
    testCompile {
        exclude group: 'xalan'
        exclude group: 'xerces'
    }
}

configurations.all*.exclude group: 'xalan'

dependencies {
    implementation 'org.codehaus.groovy:groovy:2.5.14'
    implementation ("org.jenkins-ci.plugins:job-dsl-core:${jobDslVersion}") {
        exclude module: 'xstream'
    }


    testCompile 'org.spockframework:spock-core:1.3-groovy-2.5'
    testImplementation 'org.spockframework:spock-core:2.0-M5-groovy-3.0'
    testImplementation 'cglib:cglib-nodep:2.2.2' // used by Spock

    // Jenkins test harness dependencies
    testImplementation('org.jenkins-ci.main:jenkins-test-harness:2146.v6b_f8b_1cb_d12d') { //2.34 2146.v6b_f8b_1cb_d12d
        exclude group: 'org.netbeans.modules', module: 'org-netbeans-insane'
    }
    testImplementation("org.jenkins-ci.main:jenkins-war:${jenkinsVersion}") {
        exclude group: 'org.jenkins-ci.ui', module: 'bootstrap'
    }
    testCompile("org.jenkins-ci.main:jenkins-war:${jenkinsVersion}") {
        exclude group: 'org.jenkins-ci.ui', module: 'bootstrap'
    }

    // Job DSL plugin including plugin dependencies
    testImplementation "org.jenkins-ci.plugins:job-dsl:${jobDslVersion}"
    testImplementation "org.jenkins-ci.plugins:job-dsl:${jobDslVersion}@jar"
    testImplementation 'org.jenkins-ci.plugins:structs:1.20@jar'
    testImplementation 'org.jenkins-ci.plugins:script-security:1.54@jar'
    testImplementation "org.jenkins-ci.main:jenkins-core:${jenkinsVersion}"
    testCompile "org.jenkins-ci.plugins:job-dsl:${jobDslVersion}"
    testCompile "org.jenkins-ci.plugins:job-dsl:${jobDslVersion}@jar"
    testCompile 'org.jenkins-ci.plugins:structs:1.20@jar'
    testCompile 'org.jenkins-ci.plugins:script-security:1.54@jar'

    // Plugins to install in test instance
    testPlugins 'org.jenkins-ci.plugins:cloudbees-folder:5.14'
    testPlugins 'org.jenkins-ci.plugins:credentials:2.1.10'
    testPlugins 'org.jenkins-ci.plugins:cvs:2.13'
    testPlugins 'org.jenkins-ci.plugins:ghprb:1.40.0'
    testPlugins 'org.jenkins-ci.plugins:token-macro:2.5'
    testPlugins 'org.jenkins-ci.plugins.workflow:workflow-cps-global-lib:2.7'


}

task resolveTestPlugins(type: Copy) {
    from configurations.testPlugins
    into new File(sourceSets.test.output.resourcesDir, 'test-dependencies')
    include '*.hpi'
    include '*.jpi'
    def mapping = [:]

    doFirst {
        configurations.testPlugins.resolvedConfiguration.resolvedArtifacts.each {
            mapping[it.file.name] = "${it.name}.${it.extension}"
        }
    }
    rename { mapping[it] }

    doLast {
        List<String> baseNames = source*.name.collect { mapping[it] }.collect { it[0..it.lastIndexOf('.') - 1] }
        new File(destinationDir, 'index').setText(baseNames.join('n'), 'UTF-8')
    }
}

test {
    dependsOn tasks.resolveTestPlugins
    inputs.files sourceSets.jobs.groovy.srcDirs
    useJUnitPlatform()
}
```

```
# gradle.properties
jobDslVersion=1.77
jenkinsVersion= 2.445
// JobRulesSpec.groovy
package com.example

import groovy.util.FileNameFinder
import javaposse.jobdsl.dsl.DslScriptLoader
import javaposse.jobdsl.plugin.JenkinsJobManagement
import org.junit.ClassRule
import org.jvnet.hudson.test.JenkinsRule
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll

class JobRulesSpec extends Specification {
    @Shared
    @ClassRule
    private JenkinsRule jenkinsRule = new JenkinsRule()

    @Unroll
    def 'test script #file.name'() { //File file
        given:
        println "==============> ${jenkinsRule.instance}"
        def jobManagement = new JenkinsJobManagement(System.out, [:], new File('.'))

        when:
        new DslScriptLoader(jobManagement).runScript(file.text)

        then:
        noExceptionThrown()

        where:
        file << new FileNameFinder().getFileNames('src/jobs', '**/*.groovy').collect { new File(it) }
    }
}
result 

<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="net.regnology.JobRulesSpec" tests="1" skipped="0" failures="1" errors="0" timestamp="2024-02-19T16:49:41" hostname="INV-PC-432" time="0.683">
  <properties/>
  <testcase name="test script job.groovy" classname="net.regnology.JobRulesSpec" time="0.683">
    <failure message="Expected no exception to be thrown, but got 'java.lang.IllegalStateException'" type="org.spockframework.runtime.UnallowedExceptionThrownError">Expected no exception to be thrown, but got 'java.lang.IllegalStateException'
    at app//spock.lang.Specification.noExceptionThrown(Specification.java:118)
    at net.regnology.JobRulesSpec.test script #file.name(jobsRulesSpec.groovy:27)
Caused by: java.lang.IllegalStateException: Jenkins.instance is missing. Read the documentation of Jenkins.getInstanceOrNull to see what you are doing wrong.
    at jenkins.model.Jenkins.get(Jenkins.java:819)
    at javaposse.jobdsl.plugin.LookupStrategy.lambda$static$0(LookupStrategy.java:19)
    at javaposse.jobdsl.plugin.LookupStrategy.getContext(LookupStrategy.java:57)
    at javaposse.jobdsl.plugin.LookupStrategy.getItem(LookupStrategy.java:42)
    at javaposse.jobdsl.plugin.JenkinsJobManagement.createOrUpdateConfig(JenkinsJobManagement.java:136)
    at javaposse.jobdsl.dsl.AbstractDslScriptLoader.extractGeneratedJobs_closure4(AbstractDslScriptLoader.groovy:204)
    at groovy.lang.Closure.call(Closure.java:412)
    at groovy.lang.Closure.call(Closure.java:428)
    at javaposse.jobdsl.dsl.AbstractDslScriptLoader.extractGeneratedJobs(AbstractDslScriptLoader.groovy:197)
    at javaposse.jobdsl.dsl.AbstractDslScriptLoader.extractGeneratedItems(AbstractDslScriptLoader.groovy:184)
    at javaposse.jobdsl.dsl.AbstractDslScriptLoader.runScripts_closure1(AbstractDslScriptLoader.groovy:63)
    at groovy.lang.Closure.call(Closure.java:412)
    at groovy.lang.Closure.call(Closure.java:428)
    at javaposse.jobdsl.dsl.AbstractDslScriptLoader.runScripts(AbstractDslScriptLoader.groovy:46)
    at javaposse.jobdsl.dsl.AbstractDslScriptLoader.runScript(AbstractDslScriptLoader.groovy:87)
    at net.regnology.JobRulesSpec.test script #file.name(jobsRulesSpec.groovy:24)
</failure>
  </testcase>
  <system-out><![CDATA[==============> null
Processing provided DSL script
]]></system-out>
  <system-err><![CDATA[Feb 19, 2024 5:49:41 PM javaposse.jobdsl.plugin.JenkinsJobManagement createOrUpdateConfig
INFO: createOrUpdateConfig for test
]]></system-err>
</testsuite>

i take same question on jenkins test harness repository but from authors of jenkins test harness seems not possible : https://github.com/jenkinsci/jenkins-test-harness/issues/732

if you have any idea that’s great thx

regards

i try to implement unit test on job definitions into gradle project

2

Answers


  1. Chosen as BEST ANSWER

    i decide to use junit instead of spock works better now


  2. First you should make sure not to add spock-core in 1.x and 2.x version on your classpath.
    E.g. that one should do it:

    testImplementation 'org.spockframework:spock-core:2.3-groovy-2.5'
    testImplementation 'org.spockframework:spock-junit4:2.3-groovy-2.5'
    

    You do miss the needed dependency to let Spock recognize the ClassRule of your test.

    The dependency

    org.spockframework:spock-junit4:2.3-groovy-2.5
    

    is needed in your build.gradle and Jenkins should start as expected.
    See https://spockframework.org/spock/docs/2.3/extensions.html#_classrule which does mention this:

    Spock understands @org.junit.ClassRule annotations on @Shared fields when the JUnit 4 module is included. …

    Because you failed to add that dependency it failed to honor that Rule and failed your test.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search