How to automate my Junit tests using Jenkins? - jenkins

I implemented some unit and integration tests using JUnit as seen in below (the tests are all in the same class)
#Test
public void shouldReturnThirdOf0UsingClass() {
Calculator calculator = new Calculator();
double actualResult = calculator.doOperation("thirdClass", 0);
assertThat(actualResult, is(0.0));
}
#Test
public void shouldReturnThirdWhenFirstCommandIsAddSecondCommandIsMultiplyAndThirdCommandIsThird() {
Calculator calculator = new Calculator();
calculator.doOperation("add",22);
calculator.doOperation("multiply",7);
double actualResult = calculator.doOperation("third", 21.0);
assertThat(actualResult, is(7.0));
}
I am trying to build a pipeline in Jenkins and for that I am adding this task in my gradle.build (with no filter because I want to run all the tests)
test{
}
In my Jenkins pipeline I am adding this stage "Test". What do I need to add inside the stage to run my tests?
pipeline{
agent any
stages{
stage('Test'){
steps{
{
}
}
}

I would recommend to install the gradle jenkins plugin to make it quite easy.
After that you can run it like this:
pipeline{
agent any
stages{
stage('Test'){
steps{
withGradle {
sh './gradlew test'
}
}
}
}
}

Related

How to parallelize stages in Jenkins pipeline?

I have the following pipeline and I need to parallelize the javadoc generation and publishment and the execution and publish of integration tests report.
I'm trrying the following way but it doesn't seems like the pipeline is beeing parallelize.
stage('Generate and Publish Javadoc, Run and publish Integration Tests, Run and publish Mutation Tests') {
parallel {
stage('javadoc'){
stages{
stage('Generate and publish Javadoc on Linux') {
when { expression { env.OS == 'UNIX' }}
steps {
dir('') {
sh './gradlew javadoc'
javadoc javadocDir: 'build/docs/javadoc', keepAll: true
}
}
}
stage('Generate and publish Javadoc on Windows') {
when { expression { env.OS == 'BAT' }}
steps {
dir('') {
bat 'gradlew.bat javadoc'
javadoc javadocDir: 'build/docs/javadoc', keepAll: true
}
}
}
}
}
stage('integration test'){
stages{
stage('Integration Tests on Linux') {
when { expression { env.OS == 'UNIX' }}
steps {
dir('') {
sh './gradlew integrationTest'
junit '**/build/test-results/integrationTest/*.xml'
}
}
}
stage('Integration Tests on Windows') {
when { expression { env.OS == 'BAT' }}
steps {
dir('') {
bat 'gradlew.bat integrationTest'
junit '**/build/test-results/integrationTest/*.xml'
}
}
}
stage('Publish Integration Tests Report') {
steps {
dir('') {
publishHTML(target: [allowMissing : false,
alwaysLinkToLastBuild: false,
keepAll : true,
reportDir : 'build/reports/tests/integrationTest',
reportFiles : 'index.html',
reportName : 'Integration Tests Report'])
}
}
}
}
}
}
}
The following code uses the tag parallel and inside it has a stage with stages inside it. With this I expect that the tag parallel only recognizes the most exterior stages.
With this I expect that the tag parallel only recognizes the most exterior stages.
No, Jenkins should be able to recognize the nested stages as well. I have used a similar pipeline structure to what you have and the pipeline branches off into three parts, with each part containing multiple stages.
As far as I can see, there is no problem with your pipeline syntax and it's pretty much the same set of stages and steps that I use in my pipeline. So the question here is: are you sure that the pipeline isn't running in parallel? Using something like the Blue Ocean view for Jenkins should help you visualize the steps properly. If the steps aren't running in parallel, are they running sequentially?

Jenkins restart a pipeline from a specific stage

I'm executing a declarative pipeline which generates stages dynamically:
pipeline{
stages{
stage("Prepare"){
script {
//logic goes here
pkg = getAllPkgsOrderToBuild()//inconsistent
for(pkg in pkgs){
generateBuildStage("$pkg")//uses stage("build $pkg") inside
generatePublishStage("$pkg")//uses stage("publish $pkg") inside
if(lastIteratation){
testing()
}
}
}
}
}
post{
always{
reportBack to: devMail
}
}
}
And I want to give to Jenkins' users the ability to restart the pipeline from the failed stage.
Any Idea?

Jenkins pipeline stages with conditions

Can I use "jenkins job builder" and create pipeline job, which I could run only specific stages in? Something like this:
pipeline:
if (condition):
stage1:
//...
if (condition):
stage2:
//...
or
pipeline:
stage1:
if (condition):
//...
stage2:
if (condition):
//...
Yes, you can add conditions in your Jenkinsfile.
You have to define all your stages, and inside you add condition (like your second example).
You can use the when expression to do this :
https://www.jenkins.io/doc/book/pipeline/syntax/#when
You could use something like this, I hope this helps
stage ('build') {
when {
expression { condition() }
}
steps {
sh "mvn clean package "
}
}
stage ('build') {
when {
expression { condition() }
}
steps {
sh "mvn clean install"
}
}

How to get Jenkins credentials variable in all stages of my Jenkins Declarative Pipeline

How do I get Jenkins credentials variable i.e "mysqlpassword" accessible to all stages of my Jenkins Declarative Pipeline?
The below code snippet works fine and prints my credentials.
node {
stage('Getting Database Credentials') {
withCredentials([usernamePassword(credentialsId: 'mysql_creds', passwordVariable: 'mysqlpassword', usernameVariable: 'mysqlusername')])
{
creds = "\nUsername: ${mysqlusername}\nPassword: ${mysqlpassword}\n"
}
println creds
}
}
How can I incorporate the above code in my current pipeline so that mysqlusername & mysqlpassword variables are accessible to all stages across the pipeline script i.e globally.
My pipeline script layout looks like below:
pipeline { //indicate the job is written in Declarative Pipeline
agent { label 'Prod_Slave' }
environment {
STAGE_2_EXECUTED = "0"
}
stages {
stage ("First Stage") {
steps {
echo "First called in pipeline"
script {
echo "Inside script of First stage"
}
}
} // end of first stage
stage ("Second Stage") {
steps {
echo "Second stage called in pipeline"
script {
echo "Inside script of Second stage"
}
}
} // end of second stage
} //end of stages
} // end of pipeline
I m on the latest version of Jenkins.
Requesting solutions. Thank you.
You can do something like this. Here, you define you variables under environment { } and use it throughout your stages.
pipeline {
agent any
environment {
// More detail:
// https://jenkins.io/doc/book/pipeline/jenkinsfile/#usernames-and-passwords
MYSQL_CRED = credentials('mysql_creds')
}
stages {
stage('Run Some Command') {
steps{
echo "Running some command"
sh '<some-command> -u $MYSQL_CRED_USR -p $MYSQL_CRED_PSW'
}
}
}
Variables defined under environments are global to all the stages so can be used in the whole jenkinsfile.
More information about credentials() in official documentation.

Is it possible to create parallel Jenkins Declarative Pipeline stages in a loop?

I have a list of long running Gradle tasks on different sub projects in my project. I would like to run these in parallel using Jenkins declarative pipeline.
I was hoping something like this might work:
projects = [":a", ":b", ":c"]
pipeline {
stage("Deploy"){
parallel {
for(project in projects){
stage(project ) {
when {
expression {
someConditionalFunction(project)
}
}
steps {
sh "./gradlew ${project}:someLongrunningGradleTask"
}
}
}
}
}
}
Needless to say that gives a compile error since it was expecting stage instead of for. Any ideas on how to overcome this? Thanks
I was trying to reduce duplicated code in my existing Jenkinsfile using declarative pipeline syntax. Finally I was able to wrap my head around the difference between scripted and declarative syntax.
It is possible to use scripted pipeline syntax in a declarative pipeline by wrapping it with a script {} block.
Check out my example below: you will see that all three parallel stages finish at the same time after waking up from the sleep command.
def jobs = ["JobA", "JobB", "JobC"]
def parallelStagesMap = jobs.collectEntries {
["${it}" : generateStage(it)]
}
def generateStage(job) {
return {
stage("stage: ${job}") {
echo "This is ${job}."
sh script: "sleep 15"
}
}
}
pipeline {
agent any
stages {
stage('non-parallel stage') {
steps {
echo 'This stage will be executed first.'
}
}
stage('parallel stage') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
Parallel wants a map structure. You are doing this a little inside-out. Build your map and then just pass it to parallel, rather than trying to iterate inside parallel.
Option 2 on this page shows you a way to do something similar to what you are trying.
At this link you can find a complex way I did this similar to a matrix/multi-config job:

Resources