Тестирование Pipeline и SHared LibS

Станислав Овчар

stchar

pipeline

Jenkins

  • Простой pipeline
  • Ручное обновление Jenkins
  • Ручное тестирование

pipeline

JobDSL

Configuration

Seeder

Jenkins

  • CI
  • Автоматическое обновление Jenkins
  • Ручное Тестирование

pipeline

JobDSL

E2E Test

Configuration

Seeder

Jenkins

  • Почти CD
  • Jenkins нужен для Тестирования и Разработки

pipeline

JobDSL

Unit-Test

E2E Test

Configuration

Seeder

Jenkins

  • Нам не нужен Jenkins (ну почти)

problemS

  • Больше jobs = Больше кода = Больше работы
     
  • Нет иструментов для теcтирования и отладки
     
  • jobDSL конфигурация должна быть протестирована

E2E Tests

Unit tests 

Integration
Tests

Sandbox project

 

Разбей на модули

 

Подгрузи, запусти, проконтролируй

 

E2E Tests

Unit tests 

Integration
Tests

Проверка jobDsl конфигурации и

seeder фабрик

E2E Tests

Unit tests 

Integration
Tests

Мокирование (sh, git, parallel, shared lib)

 

Проверка логики pipeline

Demo Pipeline Test (gradle)

stchar/pipeline-dsl-seed

#> gradle test
#> git clone https://github.com/headcrabmeat/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
└── src
    └── test
        └── groovy
            ├── JobSriptsSpec.groovy    # Reads the configuration run deployment in a test environment
            └── 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 скачивает весь интернет )))

script approval

Установи job Dsl plugin

Тестирование Shared LibS

pipeline-template

Unit-Tests

  • src/test
  • template to load the lib
     
  • cp -r src vars  miylib@master
  • gradle test

src, vars

Demo Shared Lib Test (gradle)

stchar/pipeline-sharedlib-testharness

#> gradle test
#> git clone https://github.com/headcrabmeat/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
Made with Slides.com