Home >Backend Development >PHP Tutorial >Re-Introducing Jenkins: Automated Testing with Pipelines
Core points
As applications become more complex—including Composer dependencies, Webpack build scripts, and every environment variable—we inevitably reach a point where testing all these different complexities becomes slow And it's laborious, especially when every test requires the removal and reconstruction of the entire environment. Likewise, code styles can skew over time, and creating a deployment archive that can be used for production requires a specific set of steps.
Suppose to test the application, the following steps are required:
composer install
to make sure the dependencies are installedphp -l
on each PHP file in the code base to check for syntax errorsIf any of these steps fails, the software should be deemed unsuitable for deployment until the error is resolved. As the software becomes more complex and the number of tests increases over time, it can take several minutes to run a full test suite, which slows down the developer and, in turn, slows down the release process.
To overcome this problem, build servers can be introduced in the development workflow. The build server runs a piece of software that allows you to run a series of steps repeatedly, and if one of them fails, the build server can notify you of the problem. If you have been involved in open source projects, you may have seen practical applications for building servers such as TravisCI or CircleCI. For example, each pull request for a Laravel project is tested by TravisCI to ensure that changes do not break any tests, and StyleCI then ensures that the code changes match the project code style.
Jenkins is a popular open source build server that released version 2.0 this year. One of the main features of this new release is to include the (previously optional) Pipeline plugin as a core feature.
Pipeline is a set of fully customizable steps that can be run sequentially to test and build code. Pipeline is written in Groovy scripting language and it has very simple syntax and is easy to get started. For example, if you want to describe the test step described earlier as Pipeline, it might look something like this:
<code class="language-groovy">node { stage("composer_install") { sh 'composer install' } stage("php_lint") { sh 'find . -name "*.php" -print0 | xargs -0 -n1 php -l' } stage("phpunit") { sh 'vendor/bin/phpunit' } stage("codeception") { sh 'vendor/bin/codecept run' } }</code>The
node
statement tells Jenkins to assign a separate build node (Jenkins can run in single-server mode or multi-node settings). node
There are multiple stages in the block, each stage performs a specific operation. Jenkins will run each stage in turn, and if any stage fails, the entire build will fail and Jenkins will stop executing.
From this simple example, additional phases of other tests can be easily added, telling Jenkins to send successful or failed build Slack notifications, push the successfully tested code to the publish branch or mark the pull request as merging.
Jenkins is very easy to install, and in this tutorial we will use Laravel Homestead to provide a consistent virtual environment so that you can use Jenkins locally.
The first step is to install Laravel Homestead – here is a useful guide. You just need to start and run the virtual machine, we don't need to configure any site in the homestead.yaml
file.
After you get up and run the Homestead virtual machine, use vagrant ssh
to log in to it.
Homestead comes with all the dependencies we need, namely Git, PHP, and Composer, so we just need to install Jenkins itself. Following the Jenkins Debian package guide, we need to perform the following steps.
Runwget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
. This command adds the code signing key to Aptitude so that the Jenkins packages from this repository are trusted.
Next, the package source list needs to be updated so that Aptitude knows about the Jenkins package repository. Execute echo "deb https://pkg.jenkins.io/debian-stable binary/" | sudo tee -a /etc/apt/sources.list
.
Finally, we need Aptitude to update the cache of its available packages and then install Jenkins:
<code class="language-groovy">node { stage("composer_install") { sh 'composer install' } stage("php_lint") { sh 'find . -name "*.php" -print0 | xargs -0 -n1 php -l' } stage("phpunit") { sh 'vendor/bin/phpunit' } stage("codeception") { sh 'vendor/bin/codecept run' } }</code>
Installing Jenkins takes about five minutes, as it also has many dependencies that need to be installed.
After installing Jenkins, open http://192.168.10.10:8080
(or the virtual host URL you configured, for example homestead.app
) in your browser and you should see a page titled "Unlock Jenkins".
In the virtual machine, run the following command - sudo cat /var/lib/jenkins/secrets/initialAdminPassword
, and a random number and alphabetical string will be printed to the console. Copy and paste the string into the text field in the browser and press Continue.
You will see two options - select "Installing the suggested plugin" and wait a few minutes until the plugin is downloaded and installed.
On the next screen, enter the details of the administrator user and press "Save and Done".
Jenkins is now installed and configured!
After setting up Jenkins, we will create a new build job that will do the following:
laravel/framework
Click on the Create New Job link (or the Create New Project link – they all do the same).
laravel
Enter a name
You will now see the configuration editor for the job. Scroll down to the Pipeline section and enter the following script:
<code class="language-bash">sudo apt-get update && sudo apt-get install jenkins</code>
Press "Save". You will be redirected to the Job Overview page and after a few seconds you will see the job start. If it doesn't start, just click the Build Now link in the left menu.
The phase view will be updated when each phase starts and ends as we define in the Pipeline script.
If you click on a stage, a overlay will appear with the log output for that stage, which is very useful for debugging. Alternatively, you can click on the job in the menu on the left and click Console.
All Jenkins jobs have their own workspace, which is a zone where you can safely create any temporary files you might need in the build zone. The workspace location for this job can be found in /var/lib/jenkins/workspace/laravel
. By default, Jenkins does not clear this workspace for every build. If you need to do this, you can add a phase to the beginning of the Pipeline script as follows:
<code class="language-groovy">node { stage("composer_install") { sh 'composer install' } stage("php_lint") { sh 'find . -name "*.php" -print0 | xargs -0 -n1 php -l' } stage("phpunit") { sh 'vendor/bin/phpunit' } stage("codeception") { sh 'vendor/bin/codecept run' } }</code>
For our first job, we edited the Pipeline script in the job settings interface. However, it would be more useful to save this script in version control with our code.
Using Jenkins' Pipeline, you can write Pipeline as a Jenkinsfile script in the root directory of the code repository and it will be discovered and run. Its concept is similar to a .travis.yml
or .circleci.yml
file that you may already be familiar with.
On the laravel/framework
Github project page, click the "fork" button in the upper right corner, and then click the profile in the pop-up window.
Create a new branch named jenkinsfile
and then create a new file (you can do this directly in Github and you don't have to clone the repository if you don't need it).
Enter the following script and submit the file:
<code class="language-bash">sudo apt-get update && sudo apt-get install jenkins</code>
Now return to Jenkins and click the "Configuration" button in the menu on the left. Scroll down to the Pipeline section and update the Definition drop-down menu from the Pipeline script to SCM.
Enter details of the repository you have forked and click Save.
On the Job Overview screen, click Build Now in the menu on the left. You should have a successful build.
Most software projects use multiple branches in the repository to define different stages of the project. For example:
For each branch you may want to run many custom operations - for example, whenever there is a commit from the master or develop branch, you want to run full unit and integration tests, while on all other branches, only units Testing is enough.
Jenkinsfile is written in the Groovy programming language, which means we have a complete scripting language to use.
In this example, I added an if statement to check the branch name; if it is master or develop, then Jenkins should run the integration_tests phase.
After, there is a switch statement that creates a different deployment archive and registers it to the code deployment service based on the branch name (in this example, I demonstrated how this will work with Amazon Web Service's CodeDeploy service) .
<code class="language-groovy">node { stage("composer_install") { sh 'composer install' } stage("php_lint") { sh 'find . -name "*.php" -print0 | xargs -0 -n1 php -l' } stage("phpunit") { sh 'vendor/bin/phpunit' } stage("codeception") { sh 'vendor/bin/codecept run' } }</code>
Multi-branched Pipeline jobs are also easy to set up—When creating a project, select "Multi-branched Pipeline" as the type:
Then, in the configuration screen, set the Pipeline Definition drop-down menu to the Pipeline script in SCM and enter the repository details.
Whenever the "Brand Index" option is run (it replaces the "Build Now" menu item inside the job), Jenkins will recursively iterate over each branch in the repository and for each branch with a Jenkinsfile that has recently changed, A new build for that branch will be run.
Jenkins' popularity is largely due to its extensive plugin ecosystem.
On the Jenkins home screen, click Manage Jenkins in the menu on the left, and then click Plugin Manager.
You can install and configure dozens of plug-ins, from testing plug-ins to integration with cloud services.
For example, if your team uses Slack, you can enable the Slack Notification plugin. It is configured in the main Jenkins settings screen ("Manage Jenkins" -> "Configure System") and the Slack message can then be sent as part of the Pipeline script:
<code class="language-bash">sudo apt-get update && sudo apt-get install jenkins</code>
When Jenkins is up and running on the server, the job can be easily configured to automatically build (or run branch indexes) every time a commit is pushed to the repository.
For Github projects, make sure that the Github plugin is installed and enabled, and then enable integration with the "Jenkins (Github Plugin)" service in the Github repository settings.
For Bitbucket, this is a little more complicated, and I have detailed the required steps on my blog.
You should also make sure that the Jenkins server is properly protected – users can be created manually in Jenkins, delegated authentication to Github or Bitbucket using OAuth, or connected Jenkins to your organization's LDAP directory. Again, Jenkins should always be run over SSL so that access to Jenkins cannot be easily intercepted.
The Jenkins installation also comes with a "code snippet generator" which allows you to view all enabled Pipeline functions (e.g., we already used sh, slackSend, deleteDir(), and scm). You can find a link to it in the left menu of the Job Overview screen.
Jenkins is a very powerful tool that can help improve the reliability of your software and save you and your team a lot of time. Humans are very bad at performing repetitive tasks over and over again, but computers are good at this.
If your team is slowing down due to tests that run for more than five minutes, uninstall the test to Jenkins.
Jenkins can do this if you want to automatically generate deployment archives when a new production or staging version is available.
If you want to keep an eye on code quality and discover regressions before customers discover, then Jenkins is ready to help.
Please leave any questions or comments below and let us know your most creative Jenkins Pipeline!
If you like this article, you may also find the following useful:
Jenkins is a popular open source tool that provides many benefits for automated testing. First, it provides continuous integration and continuous delivery (CI/CD), allowing developers to integrate changes into projects more frequently. This leads to early detection of potential problems and reduces repair time. Secondly, Jenkins supports various plug-ins, making them highly customizable and adaptable to different project needs. Third, it provides real-time test results and detailed reports, which helps quickly identify and resolve problems. Finally, Jenkins supports Pipeline, a set of tools that allow simple to complex delivery of Pipeline “as code” through Pipeline Domain Specific Language (DSL).
Setting up Jenkins for PHP tests involves several steps. First, you need to install Jenkins on the server. After installation, you can install plug-ins required for PHP testing, such as PHP plug-in, PHPUnit plug-in, etc. After installing the plugin, you can create a new Jenkins job and configure it for your PHP project. This includes setting up source code management, building triggers, and building steps. In the build step, you can specify the command to run the PHP test. Once the configuration is complete, the job can be run, and Jenkins will perform the test and provide a detailed report.
Jenkins works with PHPUnit by performing PHPUnit tests in Jenkins jobs. The PHPUnit command can be specified in the build step of the Jenkins job. When the job is run, Jenkins will perform the PHPUnit test and capture the results. The results are then displayed in the Jenkins dashboard, providing a detailed report on the test execution. This includes the number of tests that are run, passed, failed, and skipped, as well as code coverage.
The correct workflow for a Jenkins PHP application using PHPUnit usually includes the following steps: First, check out the source code from the version control system. Next, install any dependencies, such as Composer for PHP project. Then, run the PHPUnit test. The test results are then collected and displayed in the Jenkins dashboard. If any test fails, the build is marked as failed. Otherwise, the build is marked as successful. This workflow can be automated using Jenkins Pipeline for continuous integration and delivery.
PHPUnit and JUnit results can be parsed in Jenkins using the JUnit plugin. After running the PHPUnit test, you can generate a JUnit XML report. The JUnit plugin in Jenkins can then parse this report. In the post-build operation of a Jenkins job, you can add the "Publish JUnit Test Results Report" operation and specify the location of the JUnit XML report. Jenkins then parses the report and displays the results in the dashboard. This includes the number of tests that were run, passed, failed, and skipped, as well as test duration and trends.
The above is the detailed content of Re-Introducing Jenkins: Automated Testing with Pipelines. For more information, please follow other related articles on the PHP Chinese website!