In the fast-moving world of technology, companies need to release new features and fixes as fast as possible. CI/CD (continuous integration/continuous delivery) is the process of releasing features as they are developed. Here, we look at what this means and what tools it requires.
There was a time when most software was delivered as monolithic native applications. Updates would be released every few months or even years. Each application was completely self-contained and ran locally. But, starting with the explosion in mobile apps, the world has changed. Nowadays, more and more applications run in the cloud and use web UIs. These web applications bring two major benefits. Firstly, they are now accessible on a much wider range of platforms. Secondly, companies can respond more quickly to the needs of their users. This means they can stay competitive in a rapidly evolving market.
These changes have only been possible thanks to a set of techniques collectively referred to as CI/CD or continuous integration and continuous delivery. In this blog, I will explain what these actually are, and then explore some of the tools that help make this possible. At the end, we will see why continuous testing should also be included in any CI/CD toolchain.
The development process
Before we can look at CI/CD you need to be familiar with some of the terminology related to the development process. Your codebase consists of a master branch, from which the final software is built, and a number of other branches. Each developer team will typically have their own branch of code. The idea is to allow them to develop and unit test new features in isolation from all the other teams.
In the traditional SDLC, these branches are merged into master when you are ready to create a new release. This means that often dozens of new features from each team are being merged at the same time. As any project manager will tell you, this always triggers dozens of “merge conflicts” where two teams have been working on the same file. Resolving these conflicts takes time and skill.
Having merged all the code, you then start testing it. The chances are that the code will contain quite a lot of bugs (since there are lots of new features). The amount of new code makes these bugs elusive and hard to track down. Even once you have found the code that is at fault, the developers now need to go back to something they may have written weeks or months before. This all takes time and delays the delivery of your new release.
What is continuous integration?
Some years ago, people realized that you don’t have to integrate all your new code in one huge merge. Indeed, as we saw above, this is usually a pretty bad idea. So, they started to look at approaches for integrating new features as they were developed. This process became known as continuous integration. As soon as a feature is stable and passes unit testing, a merge request is made asking for it to be added into the master branch. This means the master branch always contains all the latest features. This, in turn, allows the QA team to start developing tests for these new features earlier in the development process.
So far, so simple. However, the problem is that each time some new code is added to master you need to check that it builds properly, that all unit tests pass, and that it integrates cleanly with the existing code. Also, each team has to constantly update the codebase they are working on by pulling in the new code from other teams. This ensures that they are working with the latest codebase. Doing this process manually would quickly become a pain once your dev team is more than 3 or 4 people.
What is continuous delivery?
The traditional SDLC, with releases every few months, works well for software targeting the corporate desktop market. However, most software is now based on web or mobile applications. Even Microsoft Office is now available as an online service, rather than a monolithic download. Staying competitive in this fast-changing market requires the ability to release new features as rapidly as possible. The time between your product team suggesting a new feature to that feature reaching your users should be weeks at most.
This process is referred to as continuous delivery or CD. While it is usually grouped as CI/CD, it is actually a separate concept. Most companies use some form of CI but fewer of them use CI/CD. This is because CD brings its own particular challenges.
Every time you add a new feature you need to do a full set of regression tests on your software. You also need to add tests for that new feature. The problem is, doing this manually will take days. And script-based test automation has its own problems. Firstly, each time you make changes, your existing test scripts often break. Fixing these takes time. Secondly, creating new tests is a slow and painful process. Meaning most companies never achieve 100% test automation coverage in the first place.
The other problem with frequent releases is that you risk destabilizing your production environment. This means you will need to adopt the DevOps approach to releases. In other words, test the release in a staging environment first. Instrument your production environment, and monitor exactly how the new release impacts things like responsiveness, load, etc. If you see things change, immediately roll back the new feature. Other strategies include dark launching and canary testing.
Fortunately, there are a whole host of tools that are designed to make CI and CD simple. Probably the most famous of these is Jenkins. Originally developed by Sun in 2004, Jenkins has gone on to be the most popular SDLC automation server. In simple terms, its job is to look for any new code that is being pushed to master (a merge request). It will build the new code and trigger a set of unit and integration tests (NB this means the code needs to include its own unit tests). If these tests pass, Jenkins will allow the code to be merged. It will also notify everyone that the code has been merged. Usually, developers pull the latest code version from master to their local branch every day. Other popular CI tools include Buddy, Travis, and TeamCity, and a quick Google will reveal a list of dozens of others.
Most mainstream CI tools also allow you to do CD (indeed, most refer to themselves as CI/CD tools). However, you will need to provide integrations/hooks to allow the CD tool to access your deployment toolchain. For most web applications, deployment is quite a tricky problem. You can’t just shut down your service and restart it without damaging your customer experience. So instead, you can start a new version of your environment and migrate customers to it using your load balancer.
Many companies manage to work around the problems with CI/CD. But usually, it requires significant resources. So, what can you do if you are more resource-constrained? The best advice is to adopt continuous testing.
Continuous testing implies testing your code the moment it is built. This can only be achieved if you can automate all your regression testing. As mentioned before, this is just not possible using traditional test scripting (e.g. Selenium). Instead, you need to find an autonomous test solution.
Here at Functionize, we have developed an intelligent test agent that dramatically simplifies the process of creating, executing, and analyzing UI tests. It uses a range of AI techniques including natural language processing, machine learning, deep learning, and computer vision. Tests are created from test plans in plain English using our Adaptive Language Processing™. They work on any browser and platform thanks to the way our system learns your UI. They are virtually maintenance-free with self-healing tests and root-cause analysis solving most problems. And test analysis includes visual comparisons and detailed insights into page load and responsiveness times. And of course, we offer simple integration with all major CI/CD tools.
Putting it all together
A full modern CI/CD pipeline should work as follows:
Each time a new push-request is made, the new code is checked for stability. Having been merged into master, a new build is created. This build is deployed to staging and then subjected to a full set of regression tests and smoke tests by your continuous test tool. If all tests pass, the new build is deployed to production, possibly using canary testing or sequential deployment to minimize the risk of disruption to users. All this is eminently possible and allows even a small team to release with the same velocity as big players like Google.