Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add NonCPS annotation to test a groovy class used in Jenkins

Tags:

jenkins

groovy

I'm new to groovy. Been using it for a few weeks. I wrote a class that is used in Jenkins as a shared library. The simple methods and structure works fine.

But I'm planning to make it bigger, so I want to add unit tests to it. Right now I just want to import the class in a script, and run some asserts. But I get the following error:

unable to resolve class NonCPS ,  unable to find class for annotation
@ line 51, column 2.
    @NonCPS

The annotation is required by Jenkins.

The library (which again works) something like:

class MyTestClass implements Serializable {
  MyTestClass() { }
  @NonCPS
  def testMethod() { }

in the script I call

import com.blabla.MyTestClass
...
test = new MyTestClass()

if I just comment the annotation for testing it works. I've been searching around and have seem some pretty cool projects to test Jenkins pipelines including their shared libraries, but I'm a little confused right now I would like to just get this tests before using more sophisticated things.

From the groovy documentation, I understand that the annotation should go in a class definition and not a method (is this correct?) but then how is it that this works when being run on Jenkins?

like image 274
cauchi Avatar asked Aug 15 '18 10:08

cauchi


People also ask

What is NonCPS in Jenkins?

When you put @NonCPS on a method, Jenkins will execute the entire method in one go without the ability to pause. Also, you're not allowed to reference any pipeline steps or CPS transformed methods from within an @NonCPS annotated method.

Are Jenkinsfiles written in Groovy?

The Jenkinsfile is written using the Groovy Domain-Specific Language and can be generated using a text editor or the Jenkins instance configuration tab. The Declarative Pipelines is a relatively new feature that supports the concept of code pipeline.

What is SH in Jenkins Pipeline?

On Linux, BSD, and Mac OS (Unix-like) systems, the sh step is used to execute a shell command in a Pipeline. Jenkinsfile (Declarative Pipeline) pipeline { agent any stages { stage('Build') { steps { sh 'echo "Hello World"' sh ''' echo "Multiline shell steps works too" ls -lah ''' } } } }


1 Answers

If you want to compile your shared library outside Jenkins runtime environment then you have to add groovy-cps dependency to your classpath and add an import:

import com.cloudbees.groovy.cps.NonCPS

to the class that uses @NonCPS annotation. It does not break anything - Jenkins when prepares runtime environment for Jenkinsfile execution it adds the same import and when this import is present it does not make any collision.

I would also recommend using Gradle to define dependencies and build your shared library on CI server. The minimum build.gradle file may look like this:

apply plugin: 'groovy'
apply plugin: 'idea'

repositories {
  mavenCentral()
}

sourceSets {
  main {
    groovy {
      srcDirs = ['src', 'vars']
    }
  }
  test {
    groovy {
      srcDirs = ['test']
    }
  }
}

dependencies {
  compile 'com.cloudbees:groovy-cps:1.22'
  compile 'org.codehaus.groovy:groovy-all:2.4.12'

  testCompile 'org.spockframework:spock-core:1.1-groovy-2.4'
}

It uses src and vars as a source files directories and test as a unit test directory. My shared library directory structure usually looks like this:

├── build.gradle
├── Jenkinsfile
├── src
│   └── com
│       └── foo
├── test
│   ├── com
│   │   └── foo
│   └── vars
│       └── myVarSpec.groovy
└── vars
    └── myVar.groovy

In this example we use 2 compile time dependencies - groovy-cps and groovy-all, and Spock Framework for unit tests. Thanks to this you can run unit tests inside your IDE as well as on CI server with gradle test command.

Jenkins pipeline unit test library

When running a simple unit tests is not enough, consider using JenkinsPipelineUnit library that allows you test your Jenkinsfiles including shared libraries. This is a great library that speeds up development and you can test your pipeline behavior in just a couple of milliseconds. This library works with JUnit, however there is some 3rd party wrapper that brings this library to Spock (I haven't test it though).

like image 151
Szymon Stepniak Avatar answered Oct 14 '22 04:10

Szymon Stepniak