Test Jenkins Pipeline And SHared LIBRARIES
Stanislav Ovchar

stchar
pipeline
Jenkins
- Simple pipline
- in-browser editor
- Manual testing
pipeline
JobDSL
Configuration
Seeder
Jenkins
- CI
- Generate jobs with a script
- Manual testing
pipeline
JobDSL
E2E Test
Configuration
Seeder
Jenkins
- Almost CD
- Test and Development require Jenkins instance
pipeline
JobDSL
Unit-Test
E2E Test
Configuration
Seeder
Jenkins
- Jobs could be partially tested on the localhost
problemS
-
more jobs = more code = more efforts
-
Jenkins out of the box has a lack of framework or tools to debug and test
- jobDSL configuration should be tested as well
E2E Tests
Unit tests
Integration
Tests
Sandbox project
Split big pipeline in small pieces
load'em, test'em one by one
E2E Tests
Unit tests
Integration
Tests
@JenkinsRule
@DockerRule
Verify jobDsl configuration and your seeder factory
Test Release mail
Test input step
E2E Tests
Unit tests
Integration
Tests
Mock (sh, git, parallel, shared lib)
Check pipeline "business-logic"
Demo Pipeline Test (gradle)
stchar/pipeline-dsl-seed
#> ./gradlew test
#> git clone https://github.com/stchar/pipeline-dsl-seed.git
.
├── jobs
│ ├── config.groovy # contains a configuration of jobs to deploy
│ │
│ ├── seeder.groovy # Groovy script to seed jobs with provided configuration
│ │
│ ├── seed # A project to test and publish
│ │ │ # your Jenkins jobs
│ │ │
│ │ ├── dsl
│ │ │ └── job-publisher.groovy # default input arguments
│ │ │ # configuration to call seeder script
| │ │ # and is used to sand-boxing the projects
│ │ └── pipeline
│ │ └── job-publisher.groovy # Contains pipeline script to read the
| │ # configuration, and to call seeder script
│ │
│ └── template # project with examples of scripts
│ ├── dsl
│ │ └── template.groovy
│ ├── pipeline
│ │ └── template.groovy
│ └── test
│ └── template_SUITE.groovy # e2e test
└── src
└── test
└── groovy
├── JobSriptsSpec.groovy # Reads the configuration
│ # runs deployment in a test environment
│
├── TestJobPublisher.groovy # Test job deployment script
│
└── TestTemplateJob.groovy # Example of junit tests written using JenkinsPipelineUnit
# to test template job
// file: jobs/template/pipeline/template.groovy
node() {
echo "Hello World!"
}
// file: jobs/template/dsl/template.groovy
def pipeline(dslFactory,seed_ref,job) {
if (seed_ref =~ /master/) {
_quietPeriod = 10
} else {
_quietPeriod = 1
}
dslFactory.with {
quietPeriod(_quietPeriod)
concurrentBuild(true)
}
}
// file: src/test/groovy/TestTemplateJob.groovy
import org.junit.Before
import org.junit.Test
import static org.junit.Assert.assertTrue
import com.lesfurets.jenkins.unit.BasePipelineTest
import static com.lesfurets.jenkins.unit.MethodCall.callArgsToString
class TestTemplateJob extends BasePipelineTest {
@Override
@Before
void setUp() throws Exception {
scriptRoots += 'jobs'
super.setUp()
}
// ...
}
// file: src/test/groovy/TestTemplateJob.groovy
import static com.lesfurets.jenkins.unit.MethodCall.callArgsToString
...
@Test
void should_print_property_value() {
def script = runScript('template/pipeline/template.groovy')
def expectedValue = 'Hello World!'
assertTrue(helper.callStack.findAll { call ->
call.methodName == 'echo'
}.any { call ->
callArgsToString(call).contains(expectedValue)
})
}
Demo Pipeline Test (docker)
stchar/pipeline-dsl-seed
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3c943db4: defining beans [authenticationManager]; root of factory hierarchy
Jul 27, 2017 4:23:10 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.web.context.support.StaticWebApplicationContext@57615d2e: display name [Root WebApplicationContext]; startup date [Thu Jul 27 16:23:10 UTC 2017]; root of context hierarchy
Jul 27, 2017 4:23:10 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.web.context.support.StaticWebApplicationContext@57615d2e]: org.springframework.beans.factory.support.DefaultListableBeanFactory@6e050b6c
Jul 27, 2017 4:23:10 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6e050b6c: defining beans [filter,legacy]; root of factory hierarchy
Jul 27, 2017 4:23:10 PM jenkins.install.SetupWizard init
INFO:
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
a7290d982c39456e81c2be180e4301ef
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
Jul 27, 2017 4:23:18 PM hudson.model.UpdateSite updateData
INFO: Obtained the latest update center data file for UpdateSource default
Jul 27, 2017 4:23:18 PM hudson.model.UpdateSite updateData
INFO: Obtained the latest update center data file for UpdateSource d
Ctrl+C
#> docker run -p 8080:8080 -p 50000:50000 jenkins
Ctrl+V





jobs/seed/pipeline/job-publisher.groovy


gradle downloads the entire internet)))
script approval
Install jobDsl plugin
TeSt Shared Libraries
pipeline-template
Unit-Tests
- src/test
-
template to load the lib
- cp -r src vars miylib@master
- gradle check
- JenkinsPipelineUnit
- @JenkinsRule
src, vars
Integration
Tests
Demo Shared Lib Test (gradle)
stchar/pipeline-sharedlib-testharness
#> gradle check
#> git clone https://github.com/stchar/pipeline-sharedlib-testharness.git
.
│
├── build.gradle
│
├── build
│ │
│ └── libs
│ └── jenkins-commons@master
│ └── jenkins-commons@feature
│
├── jobs
│ └── template
│ └── pipeline
│ └── template.groovy
│
├── src
│ ├── org
│ │ └── hcm
│ │ └── libjenkins
│ │ └── Gitlab.groovy
│ └── test
│ └── groovy
│ └── TestJenkinsCommonLib.groovy
└── vars
└── gitlab_stage.groovy
// file: src/test/groovy/TestJenkinsCommonLib.groovy
@Library('jenkins-commons')
import org.hcm.libjenkins.Gitlab
gitlab_lib = new Gitlab(this)
gl_stages = ['hello']
gitlabBuild(gl_stages) {
gitlab_stage(gl_stages,'hello','master',10) {
echo "Hello World!"
}
}
return this
// file: src/test/groovy/TestJenkinsCommonLib.groovy
...
class TestJenkinsCommonLib extends BasePipelineTest {
String sharedLibs = ''
@Override
@Before
void setUp() throws Exception {
scriptRoots += 'jobs'
super.setUp()
def library = library().name('jenkins-commons')
.defaultVersion("master")
.allowOverride(true)
.implicit(true)
.targetPath('build/libs')
.retriever(localSource('build/libs'))
.build()
helper.registerSharedLibrary(library)
}
}
// file: src/test/groovy/TestJenkinsCommonLib.groovy
...
@Test
void should_execute_without_errors() throws Exception {
def script = runScript("template/pipeline/template.groovy")
//printCallStack()
}
@Test
void verify_is_upstream() throws Exception {
def script = runScript("template/pipeline/template.groovy")
assertEquals('Verify is_upstream ', false, script.gitlab_lib.is_upstream('feature'))
assertEquals('Verify is_upstream ', true, script.gitlab_lib.is_upstream('master'))
assertEquals('Verify is_upstream ', true, script.gitlab_lib.is_upstream('rel-1.2.3'))
//printCallStack()
}
LINKS
- https://github.com/stchar/pipeline-dsl-seed
- https://github.com/stchar/pipeline-sharedlib-testharness
- https://github.com/lesfurets/JenkinsPipelineUnit
- https://github.com/sheehan/job-dsl-gradle-example
- https://github.com/mkobit/jenkins-pipeline-shared-libraries-gradle-plugin
JPipelineUnit en_US
By Stas Ovchar
JPipelineUnit en_US
CD for CD and X as code in Jenkins pipeline world. Testing of Jenkins pipelines and shared libraries with different frameworks.
- 953