Parallel Testing With A Single File Via Jenkins In Docker


Overview

This blog shows you one of the Jenkins Pipeline examples in a practical automation project.

It is for anyone who wants to know how to apply Jenkins Pipeline to an automation project. Or if you are new to Jenkins and want to get your hands dirty practicing on it, then this post is for you.

The blog post does not explain docker in depth but you can visit some reference links for details. Instead, it focuses on configuring Jenkins job and parallel testing with a single file across multiple processes.

And it is designed to work on Windows 10 Pro only, not on a macOS or Linux machine.

Before continuing, ensure you have installed the following tools

  1. Docker
    You can install the latest version of Docker Desktop which contains both Docker and Docker-Compose tools
    ref: download link
  2. GitLab
    During the steps, you will be required to download/upload the source code to GitLab. Ensure you have installed and configured Git and authentication to your GitLab

Jenkins Server Startup

The steps in this part will do the following

  • download Jenkins docker image
  • install Docker Pipeline plugin in Jenkins server
  • perform initial configuration for Jenkins

The plugin is required for using docker.image in Scripted Pipeline. When the Pipeline executes, Jenkins will automatically start the specified container and execute the defined steps within it.
If you are currently working from home, VPN connection may prevent installing Jenkins plugins. Please consider to disconnect VPN temporarily before continuing the next steps.

Jenkinsfile (Scripted Pipeline)
node {
    /* Requires the Docker Pipeline plugin to be installed */
    stage('Test') {
    	docker.image('python:3.6.8-alpine').inside {
            sh 'python --version'
        }
    }
}

ref: Using Docker with Pipeline

Now please follow the next step-by-step

  1. Run Docker Desktop

  2. Run Jenkins in Docker Container
    Refer to the official Jenkins document to follow step# 1-6 on Windows. Or to keep it simple and avoid typo, you can use docker-compose tool with only 2 commands docker-compose build and docker-compose up -d inside project root folder. You will need to download source code from GitLab repository (*the link is TBD) first.
    ref: create docker-compose
    Two ways above are equivalent to start up Jenkins in Docker.

    • When doing Create First Admin User then select Skip and continue as admin
    • And in the remaining screens, select option as default (blue highlight)
  3. Then Welcome screen is displayed

  4. Change password using Configure button

  5. Log in again with a new password

  6. Then Welcome screen is displayed again


Create & Configure Pipeline Job

The steps in this part will create the first Jenkins Pipeline job and configure it to do the following

  • download the latest source code from GitLab
  • run test with current source code
  • upload test result to GitLab

In the upcoming configuration, we will use an existing GitLab repository (*the link is TBD) which contains a simple Python test.
The function test_read_write_input_file focuses on reading and writing a single CSV file parallel. To achieve that goal, we will use pytest as test runner and pytest-xdist & filelock plugins.
The screenshot below demonstrates how to lock file with 2 processes (gw0 & gw1) parallel. Only one process can lock the file at a time. When the process gw0 unlock/release the file then only the process gw1 can lock it again.

In this test, only one function test_read_write_input_file is collected by pytest. We will run the test on every process by specifying the option --dist=each in pytest command. It means that the test is run twice parallel, one on gw0 and one on gw1.
The full command to run the test is pytest -n 2 --dist=each
You can change the number of processes and dist options in the command by referring the links as below.

ref: pytest-xdist, pytest-xdist options

Now please follow the next step-by-step

  1. Create a new item for Pipeline job
  2. Copy the script to pipeline definition and then save it
node {
    stage('Download source code from Git') {
        // the below will clone your repo and will be checked out to master branch by default
        git credentialsId: 'auto-credentials', url: 'https://gitlab.shiftasia.com/thuanpham/jenkins-docker-sample.git', branch: 'master'
    }
    stage('Run Test') {
        // download docker image with specific version
        docker.image('python:3.6.8-alpine').inside {
            // check Python version
            sh 'python --version'
            sh 'pip list'
            withEnv(["HOME=${env.WORKSPACE}"]) {
                // install libraries required for testing
                sh 'pip install -r requirements.txt --user'
                // check libraries installed
                sh 'pip list'
                // execute test
                sh 'python -m pytest -n 2 --dist=each'
            }
        }
    }
    stage('Upload test result to Git') {
        def file='input.csv'
        sh 'git add '+file
        sh '''git commit -m "Commit from Jenkins $(date +"%d-%m-%Y")" '''
        withCredentials([usernamePassword(credentialsId: 'auto-credentials', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
            sh "git push https://'$USERNAME:$PASSWORD'@gitlab.shiftasia.com/thuanpham/jenkins-docker-sample.git master"
        }
    }
}

For pipeline syntax, click the link for details

You can generate the following command by using it

git credentialsId: 'auto-credentials', url: 'https://gitlab.shiftasia.com/thuanpham/jenkins-docker-sample.git'




  1. Access the docker container to configure Git
D:\projects\jenkins-docker-sample>docker exec -it jenkins-blueocean bash
jenkins@80a042ac8a34:/$ git config --list
jenkins@80a042ac8a34:/$ git config --global user.name "Jenkins"
jenkins@80a042ac8a34:/$ git config --global user.email "jenkins@test.com"
jenkins@80a042ac8a34:/$ git config --list
user.name=Jenkins
user.email=jenkins@test.com
jenkins@80a042ac8a34:/$ exit
exit

D:\projects\jenkins-docker-sample>

ref: access docker container by command

  1. Run the job
    If you are currently working from home, VPN connection is required to run the job. The job will download source code from GitLab and upload file changes to it.
  2. Check the console log




  3. Check GitLab repository for the latest commit from Jenkins
  4. Stop Jenkins server by command docker stop jenkins-blueocean jenkins-docker. Or if you are using docker-compose tool, please use the command docker-compose down

ref: stop jenkins by command

  1. Restart Jenkins server by the command docker-compose up -d

That's all for the example, thanks for reading.

Enjoy!