Code & Data Security

Resource Center

Continuous Integration in Agile Development

February 26, 2014

Tiny Url for this post: https://tinyurl.com/yxhl5jbh

Introduction

The modern software development process has adopted iterative & incremental approach rather than the traditional approach that is linear and not flexible to changes.

Agile processes have gained great acceptance in commercial arena over the past many years. Agile deals with volatile requirements and uses a number of methods such as simple planning, short iteration, earlier release and regular feedback. These techniques enable agile methodology to deliver the product in a short time span when compared to the traditional models.

One of the key principles of agile process is doing everything in small steps but continuously. That is, developing in small iterations, estimating small amounts of work and refactoring in small steps. As Martin Fowler defines this as frequency reduces difficulty – this is a specialization of divide and conquer.

Every aspect of the development is continually revisited throughout the lifecycle in agile methodology. Agile teams are very useful in shifting the focus to a flexible & holistic design and development strategy.

The process flow of the teams is depicted as below. Here the planning and the architecture teams define the capabilities for the system to be developed. The pre-planning period includes the technical planning, needs analysis, requirements articulation and creation of architecture framework. Inputs into this pre-planning phase include customer needed capabilities and the output is a vision, roadmap and architecture. During the pre-planning phase, the planning team defines the scope and deliverables of the project, and the architecture team establishes the vision, architecture and a product backlog. Few elements of the architecture may be identified for analysis and elaboration later in the implementation cycle.

The output from the pre-planning phase flows into the first iteration. The architecture team updates the capabilities backlog and prepares materials for implementation team. These materials may include requirements, capabilities and user experience. Architecture team may also work with implementation team to maintain the architecture as the detailed design evolves and assist developers in aligning the product to the proposed requirements. Integration and Test team implements the test environment. In subsequent iterations, the finished product from all teams will be tested by the integration and test team to verify the requirements internally and with customers.

If any changes are required to the architecture then architecture team revises the architecture in order to support upcoming capability development. This may include architecture revision, trade studies and database revision. Here the goal is to provide a modular systems architecture that is resilient to change. All iterations will continue until the release is complete. The release is demonstrated to stakeholders & planning team for review and acceptance. Requested changes are then planned into the next release. At the demonstration of the final release, developers check whether the final software meets all requirements.


Necessity of continuous integration in agile development

Continuous integration (CI) is a popular practice in agile methodology. CI means the team should keep the system fully integrated at all times. Integration can happen many times a day. Here the point is that CI detects enough bugs to be worth the cost. CI minimizes the time spent on searching bugs and identifies compatibility issues very early.

Enterprises that have implemented agile processes have already seen great improvements both in cost & stability and in the utility of the software. Continuous integration highlights the cultural shifts required to become an agile enterprise. The key to building a culture that supports CI is to make sure that it works the first time.

Continuous integration takes some effort. If you are committed to Agile then it is not a luxury but a necessity. The effort put into it will reflect in the quality of code, responsiveness of the team and in the confidence of a job well done. But don’t get caught up with the word ‘continuous’. As integration occurs only at certain intervals or when triggered by an event, CI is actually not continuous. Integration is continuous – means it always happens routinely.

CI is associated with the concepts of eliminating waste and rapid feedback. Waste is considered as something that doesn’t add value to customers.

There are few methods to eliminate waste. An effective method is to identify and address antipatterns in software delivery process. Ineffective or counterproductive practices are known as Antipatterns, which produce bad consequences. Let’s explore a couple of them:

Suboptimal branching and merging

The activity of parallel development (especially in case of large projects) leads to lots of branching. Merging the branches could be a painful process. When branches become more distinct, the merging becomes even more complex. We can mitigate this problem by testing and integrating more frequently, and also by using CI server to build the software automatically as integration takes place.

Long test cycles

When the development team passes the work to the QA team, sometimes a lack of automation can lead to long test cycles. Manual testing and using spreadsheets to document the outcomes may affect the delivery of the release by impacting the product’s quality.

To avoid this problem, a testing framework should be incorporated so that the build process includes a variety of testing such as unit testing, integration testing, functional & nonfunctional testing and acceptance testing, with a feedback mechanism built in. The framework must also include thresholds for testing. For instance, in case of unit testing, there could be a minimum of 75 to 80 percent coverage. If it drops below 75% then the coverage should be improved by marking the build as ‘bad’.

How continuous integration minimizes project friction?

Friction is clearly visible in a more iterative process. You can make use of some software engineering principles that enable iterative process and lubricate the friction. One of these principles is continuous integration. CI is the practice of doing integrated builds very frequently, normally upon each check-in to the source control.

You should use a version control repository to perform CI. The purpose of a repository is to manage changes to source code and other things like documentation. The repository lets you to go back in time and access different versions of code.


When you commit changes to the source code repository, the CI server runs an integration build. You can also configure the server to check for changes every few minutes. The server will retrieve all the files and runs build script. CI servers can also be hard scheduled to build on a regular frequency.

The CI server generates feedback i.e. it sends build and test results to a feedback system so that all stakeholders can know the status of the build. The server continues to poll for changes in the repository.

The exact types of builds you need may depend on your product and environment. Some of the different types of builds you can do with CI are shown in the following table:

While introducing CI and various builds, project teams may resist some of these changes. Let’s discuss how to overcome such resistance.


How to overcome the initial resistance?

Some major resistances include:

CI means increased maintenance

This is actually a misguided perception. Managing a robust CI system is better than managing manual processes. After setting up the system and fully integrating a project, the team can save time because it is easier to test the application and fix bugs. Maintenance takes less than an hour per week with CI process.

This is too much change and too fast

Some teams believe that there are too many processes to change in order to achieve continuous integration in case of legacy projects. But we need not implement everything at once. An incremental approach is most effective. We can start with a simple build once per day and add unit testing. As the team gets comfortable with the results, you can increase the frequency by adding a couple of additional builds per day.

Failed builds

This may occur when developers are not performing a private build before committing their code. It could be that a developer had some failed tests or forgot to check in a file. Because of the frequency of changes, rapid response is essential while using CI.

CI means additional hardware and software costs

A self-reliant integration machine is required to use CI effectively. This is normally inexpensive as compared to the costs of finding issues later in the development.

Developers have to perform these activities

It seems like CI is duplicating developer activities. Yes, developers have to perform some of these activities and they need to do this reliably & effectively in a separate environment. But an automated system can improve the efficiency & frequency of these activities and it also ensures that these activities are performed in a clean environment. This allows developers to focus on business issues of the application.

The project is too far along to add CI

It is always easy to place a new project under a CI process. But most of the work we do is maintaining existing projects. An existing project may not have unit tests, but you may use source control and need to do builds. You can get benefits from CI no matter how far along your project is.

Following a good CI process certainly involves more steps and a detailed understanding of the process. Before checking in their changes, all developers must be comfortable making the necessary changes to integrate with the rest of the system. It means they need to have a better understanding of how the entire system works. This understanding certainly has many other benefits for the team.

To make the integration work, sometimes developers must also be comfortable to make changes in other’s code. If team members have a high degree of code ownership then transitioning to CI can be hard and time consuming. If everyone is willing and able to follow the process, they will quickly identify how easier the integration process becomes for everyone and how much less time they spend waiting around for someone else to deal with integration issues.

Choosing the right continuous integration server

The CI server checks whether anything new is on the source control system. If so, it pulls the code and starts the build process. The whole process is enclosed in an infinite loop. Whenever the developer pushes anything into the source control repository, sooner or later it gets integrated.


Choosing the right CI server is not an easy task. You have to deal with both the software & hardware aspects. On the hardware side, you must determine whether you have a separate physical machine on which to build your CI server. Is it an old machine standing in the corner? (or) Is it a full blown server with 99.9% uptime (or) If you don’t have a physical machine, can you arrange a virtualized server so that every member of the team can access it?

But it is strongly recommended to dedicate a separate machine for CI server. This is because a perfectly created CI process should have as few dependencies as possible.

Some CI servers may need other services in order to extend their functionality. You are not supposed to install any additional applications on the build server unless they are taking part in the build process.

The other reason to use a dedicated continuous build machine is that you can keep it clear of any configuration changes you normally perform. So you are free from any assumptions about the installed software.

As far as hardware is concerned, more is better. The build should be as fast as possible. After putting a new feature in the source control system, every team member has to wait for the CI build to finish and check it to ensure that everything worked as expected. You need not keep developers from their work for too long. In fact, a fast CPU and fast hard drive are always cheaper than developer’s time.

When you have a dedicated integration machine ready to host CI server, you can figure out which server is right for you. Many CI servers are available and if you need to choose wisely, consider these five points:

  • How much money do you need to spend?
  • Does it support other tools you need?
  • Is it easy to use?
  • How good is the documentation and support?
  • Does it perform more than you need? – Not just now but also in future.

Best practices

Developers must change their software development habits so that CI works effectively. They have to commit code more frequently and write automated builds with tests that pass 100% of the time.

Here are few best practices:

  • Commit code frequently
  • Do not commit broken code
  • Fixing broken builds
  • Automated developer tests
  • All tests and inspections must pass
  • Running private builds
  • Tracking progress
  • Sticking with what works

Commit code frequently

In order to get the benefits of CI, developers must commit code frequently. Waiting more than a day to commit code to the repository can make integration a time consuming process and prevents team from being able to use latest changes.

Do not try to change several components all at once. Choose a small task, write tests and code, run your tests, and then commit your code to the repository.

You may also prevent having everyone commit at the same time. There will be more build errors to handle due to collisions between changes.

Do not commit broken code

A well factored build script can compile and test the code in a repeatable way. Running a private build before committing code to the repository can be regarded as a part of the software development strategy.

Fixing broken builds

A broken build prevents the build from reporting success. This can be a compilation error, a failed inspection, a database issue or failed deployment. These issues must be resolved immediately while operating in a CI environment. The project culture should reveal that fixing a broken build is a top priority. So, not just a few but every member of the team can get back to what they were doing.

Automated developer tests

A build must be fully automated. The tests must be automated to run tests for a CI system. Writing your tests in xUnit frameworks (such as NUnit or JUnit) will run these tests in an automated fashion.

All tests and inspections must pass

Automated tests are as crucial as the compilation. The team can use a general rule set of coding and design standards that all code must pass. Some advanced inspections can be added that do not fail the build, but they determine areas of the code that must be investigated thoroughly.

Running private builds

In order to avoid broken builds, developers must emulate an integration build on their local workstation IDE after finishing their unit tests. This build lets you to integrate the new working software with the working software from other team members, collecting the changes from the repository and building locally with recent changes.

Tracking Progress

The consistency of your approach to CI allows you to identify and manage trends throughout the development lifecycle. With a history of past builds on a project dashboard, project managers and developers can track the ratio of successful to unsuccessful builds and identify quality issues. Trends in coverage reports and analysis tools can help developers manage growth efficiently.

Sticking with what works

Project teams with a successful CI strategy need not change their process after their first production deliverable. Application maintenance efforts that are of short duration with limited scope will fit well into the existing approaches. As teams have been focusing on managing change throughout the lifecycle, change requests are an integral part of their work.

Conclusion

Hence, Continuous Integration deals with many components including a source control repository, an automated build system, tests, and a CI server. As source code is changed in the repository, the CI server automatically detects the changes, runs all the tests, and builds the final product, with a goal of detecting problems early in the process.

CI is about people more than tools. In order to be effective, it requires that developers check-in their code changes to the source control on a frequent basis, keep the tests complete and move immediately to address test failures as they appear.

As these test failures are highly visible and feedback is immediate, the CI server acts as an extra team member at the daily stand-up meetings, pointing out issues that have yet to be addressed and keeping the team focused on quality. A CI server can also keep track of older builds and makes it easy to ship a previous release.

Note: Continuous Integration is not meant for removing software bugs, but it enhances their detection and keeps the team members away from going in the wrong direction.

This post is also available in: French

Learn more about Seeker

More Whitepapers