It's common practice to perform an extensive testing on a Pull Request before the code is being deployed to production systems.
So far we've seen how pipeline can be built and run around a single Git branch (e.g. main or dev). Now we would like to create a new pipeline which will be triggered on every PR that is created in GitHub.
For that we will utilize Jenkins multi-branch pipeline.
- From the main Jenkins dashboard page, choose New Item, and create a Multibranch Pipeline named
pull-request-testing. - In the GitHub source section, under Discover branches configure this pipeline to discover PRs only!
- This pipeline should be defined by a Jenkinsfile called
PullRequest.Jenkinsfile. - In
mainbranch, create thePullRequest.Jenkinsfileas follows:
pipeline {
agent any
stages {
stage('Unittest') {
steps {
echo "testing"
}
}
stage('Lint') {
steps {
echo "linting"
}
}
stage('Functional test') {
steps {
echo "testing"
}
}
}
}
- Commit the Jenkinsfile and push it.
From now one, we would like to protect branch main from being merged by non-tested and reviewed branch.
- From GitHub main repo page, go to Settings, then Branches.
- Add rule for the
mainbranch as follows:- Check Require a pull request before merging.
- Check Require status checks to pass before merging and search the
continuous-integration/jenkins/branchcheck done by Jenkins. - Save the protection rule.
Your main branch is now protected and no code can be merged to it unless the PR is reviewed by other team member and passed all automatic tests done by Jenkins.
Let's implement the pull request testing pipeline.
- From branch
maincreate a new branch calledsample_featurewhich simulates some new feature that a developer is going to develop. Push the branch to remote. - In your app GitHub page, create a Pull Request from
sample_featureintomain. - Watch the triggered pipeline in Jenkins.
Unittest is a testing framework in Python that allows developers to write and run small, isolated tests for individual units of code to ensure their correctness and detect any potential bugs or issues.
-
In the
projects/app_development_I/yolo5directory, you are given directory calledtests. This is a common name for the directory containing all unittests files. The directory contains a file calledtest_allowed_file.pywhich implements unittest for theallowed_filefunction inutils.pyfile. -
Run the unittest locally (you may need to install the requirements:
pip install -r requirements.txt), check that all tests are passed:
python3 -m pytest --junitxml results.xml tests-
Integrate the unittesting in
PullRequest.Jenkinsfileunder the Unittest stage. -
You can add the following
poststep to display the tests results in the readable form:
post {
always {
junit allowEmptyResults: true, testResults: 'results.xml'
}
}
- Make sure Jenkins is blocking the PR to be merged when unittest is failed!
Pylint is a static code analyser for Python. Pylint analyses your code without actually running it. It checks for errors, enforces a coding standard, and can make suggestions about how the code could be refactored.
- Install
pylintlocally if needed. - Generate a default template for
.pylintrcfile which is a configuration file defines how Pylint should behave
pylint --generate-rcfile > .pylintrc- Lint your code locally by:
python3 -m pylint *.pyHow many warnings do you get? If you need to ignore some unuseful warning, add it to disable list in [MESSAGES CONTROL] section in your .pylintrc file.
- Integrate the unittesting in
PullRequest.Jenkinsfileunder the Lint stage. - (Bonus) Add Pylint reports to Jenkins pipeline dashboard:
- Install the Warnings Next Generation Plugin.
- Change your linting stage to be something like (make sure you understand this change):
steps { sh 'python3 -m pylint -f parseable --reports=no *.py > pylint.log' } post { always { sh 'cat pylint.log' recordIssues ( enabledForFailure: true, aggregatingResults: true, tools: [pyLint(name: 'Pylint', pattern: '**/pylint.log')] ) } }
Use parallel directive to run the test stages in parallel, while failing the whole build when one of the stages is failed.