Continuous Integration (CI) is a development process that takes automated unit testing to the next level. It automates many of the steps required to get from a bunch of source code to a shippable product while ensuring high software quality. A CI process or CI loop runs fully automated without end-user interaction. A single execution can be started by one of two events: One is a scheduled event that kicks of the CI loop. It is recommended to have the entire CI loop run at least once a day, for example nightly. The other more commonly used way to start the CI process is a trigger that fires every time a change is committed to source control.
Every time the CI loop is started, it goes through the following phases:
The phases are described in more detail below.
Building the software includes steps like compiling .NET source code or collecting and combining SQL scripts. It might also include steps to create a new database and execute those SQL scripts.
The purpose of this phase is to create a complete software package that is shippable. This can for example include steps to create an installer package that can be executed on a client's machine. It also might include a step to turn the database created in the build phase into a .dacpac or similar file.
Note, that while I am calling this package "shippable", it is at this point not yet confirmed to be fit for business. To confirm that, the process needs to go through two more phases.
In this phase the package build before is deployed. This deployment is not going against a production environment nor is it going against the development environment. Instead, the deployment is happening in a dedicated environment that is duplicating production as closely as possible. This phase confirms that the package is actually deployable and does not fail half way through.
This is the final and most important phase of the CI loop. In this phase, all the automated tests are executed. That includes all your unit tests, including .NET and T-SQL tests, but also other test types like integration tests and acceptance tests. If you have automated UI tests using tools like Selenium, Robot Framework or others, they should be included too.
Some teams even include automated performance testing in the CI process.
So, you might ask at this point, why would I go through all this trouble?
Every time the CI process runs, you get either feedback about something being broken, or you get a shippable software package. While that package might not be feature complete, it is deployable and passes all the current requirements that are expressed in tests. If you are diligent about your tests, this means that you could actually ship this package to at least your alpha or beta test customers.
But even if you are just starting out with automated tests and have a spotty test coverage of your requirements, implementing CI has many advantages. Unit testing your code is certainly beneficial. However, having unit tests alone does not cover all your bases. CI complements unit testing by providing several additional benefits.
The main advantage of implementing a CI process probably is that the entire system is build, deployed and tested on a frequent basis giving you regularly feedback about the health of the project. I will go into more detail about this and the other advantages in a follow up article about the benefits of implementing CI. Sign up to my newsletter below, and I will notify you once that article is published.