When we make assumptions in software development, we waste time and increase risks. Continuous Integration can help reduce assumptions on a project by rebuilding software whenever a change occurs in a version control system. Learn how it works.

Early in my career, I learned that developing good software comes down to consistently carrying out fundamental practices regardless of the particular technology. In my experience, one of the most significant problems in software development is assuming. If you assume a method will be passed the right parameter value, the method will fail. Assume that developers are following coding and design standards and the software will be difficult to maintain. Assume configuration files haven't changed, and you'll spend precious development hours needlessly hunting down problems that don't exist. When we make assumptions in software development, we waste time and increase risks.

Reducing Assumptions

Continuous Integration can help reduce assumptions on a project by rebuilding software whenever a change occurs in a version control system.

We may think that the latest, greatest technology will be the "silver bullet" to solve all of our problems, but it will not. At one company, one of my initial responsibilities was to incorporate good software development practices into the company—by example. Over time, we were able to implement many widely accepted practices for developing good software into the projects. Having worked on many different projects that used different methodologies, I have found that, in general, iterative projects—using the Rational Unified Process (RUP) and eXtreme Programming (XP), in my case—work best, because risks are mitigated all along the way. Developing software requires planning for change, continuously observing the results, and incrementally course-correcting based on the results. This is how CI operates. CI is the embodiment of tactics that gives us, as software developers, the ability to make changes in our code, knowing that if we break software, we'll receive immediate feedback. This immediate feedback gives us time to course-correct and adjust to change more rapidly.

CI is about the fundamentals. It may not be the most glamorous activity in software development, but integrating software is vitally important in today's complex projects. Seldom do the users of the software say to me, "Wow, I really like the way you integrated the software in the last release." And since that doesn't happen, it may seem like it isn't worthwhile to make these efforts behind the scenes. However, anyone who has developed software using a practice such as CI is empowered by a consistent and repeatable build process kicked off when a change occurs to the version control repository.

CI as a Centerpiece for Quality

Some see CI as a process of simply putting software components together. We see CI as the centerpiece of software development, as it ensures the health of software through running a build with every change. Determining the quality of software can be as easy as checking the latest integration build.

Spending some time on the nonglamorous fundamental activities in software development means there is more time to spend on the challenging, thought-provoking activities that make our jobs interesting and fun. If we don't focus on the fundamentals, such as defining the development environment and building the software, we'll be forced to perform low-level tasks later, usually at the most inconvenient times (immediately before software goes to production, for example). This is when mistakes happen as well. The discipline involved in keeping the build "in the green" frees you from worrying about whether everything is still working. It's like exercising—yes, it takes self-discipline; yes, it can be painful work—but it keeps you in shape to play in the big game, when it counts.

This chapter attempts to answer the questions that you may have when making the decision to implement the practices of CI on a project. It provides an overview of the advantages and disadvantages of CI, and covers how CI complements other software development practices. CI is not a practice that can be handed off to a project's "build master" and forgotten about. It affects every person on the software development team, so we discuss CI in terms of what all team members must practice to implement it.

What's a day of work like using CI? Let's examine Tim's experiences.

A Day in the Life of CI

As Tim opens the door to his company's suite, he views the wide-screen monitor displaying real-time information for his project. The monitor shows him that the last integration build ran successfully a few minutes ago on the CI server. It shows a list of the latest quality metrics, including coding/design standard adherence, code duplication, and so on. Tim is one of 15 developers on a Java project creating management software for an online brewery. See Figure 2-1 for a visualization of some of the activities in Tim's day.

Starting his day, Tim refactors a subsystem that was reported to have too much duplicate code based on the latest reports from the CI server. Prior to committing his changes to Subversion, he runs a private build, which compiles and runs the unit tests against the newest source code. After running this build on his machine, he commits his changes to Subversion. All the while, the CruiseControl CI server is polling the Subversion repository. A few minutes later, the CI server discovers the changes that Tim committed and runs an integration build. This integration build runs automated inspection tools to verify that all code adheres to the coding standard. Tim receives an e-mail about a coding standard violation, quickly makes the changes, and checks the source code back into Subversion. The CI server runs another build and it is successful. By reviewing the Web reports generated by the CI server, Tim finds that his recent code refactoring successfully reduced the amount of duplicate code in his subsystem.

Later in the day, another developer on the project, Lisa, runs into Tim's office.

Lisa: I think the changes you made earlier today broke the last build!

Tim: Hmm but, I ran the tests.

Lisa: Oh, I didn't have time to write tests.

Tim: Are you following the code coverage metric we have established for the project?

Because of this discussion, they decided to fail the integration build if their code coverage was below 85%. Furthermore, Lisa wrote a test for the defect and fixed the problem she discovered because of her conversation with Tim. The integration build continued to stay "in the green."

build—A set of activities performed to generate, test, inspect, and deploy software.

continuous—Technically, continuous means something that, once started, never stops. This would mean the build runs all the time; however, this isn't the case. Continuous, in the context of CI, is more like continual, and in the case of CI servers, a process continually runs, polling for changes to the version control repository. If the CI server discovers changes, it executes a build script.

Continuous Integration—"A software development practice where members of a team integrate their work frequently, usually each person integrates at least daily—leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly."1

development environment—The environment in which software is written. This can include the IDE, build scripts, tools, third-party libraries, servers, and configuration files.

inspection—Analysis of source code/bytecode for the internal quality attributes. In the context of this book, we refer to the automated aspects (static and runtime analysis) as software inspection.

integration—The act of combining separate source code artifacts together to determine how they work as a whole.

integration build—An integration build is the act of combining software components (programs and files) into a software system. This build includes multiple components on bigger projects or only low-level compiled source files on smaller projects. In our everyday life, we tend to use the terms build and integration build interchangeably, but for the purposes of this book we make the distinction that an integration build is performed by a separate integration build machine.

private (system) build—Running a build locally on your workstation before committing your changes to the version control repository, to lessen the chances that your recent changes break the integration build.2

quality—The Free On-Line Dictionary of Computing3 defines quality as "an essential and distinguishing attribute of something..." and "superior grade." The term quality is often overused, and some seem to think it is based on perception. In this book, we take the stance that quality is a measurable specification just like any other. This means you can identify specific metrics of quality, such as maintainability, extensibility, security, performance, and readability.

release build—Readies the software for release to users. It may occur at the end of an iteration or some other milestone, and it must include any acceptance tests and may include more extensive performance and load tests.

risk—The potential for a problem to occur. A risk that has been realized is known as a problem. We focus on the higher-priority risks (damage to our interests and goals) that have the highest likelihood of occurring.

testing—The general process of verifying that software works as designed. Furthermore, we define developer tests into multiple categories, such as unit tests, component tests, and system tests, all of which verify that objects, packages, modules, and the software system work as designed. There are many other types of tests, such as functional and load tests, but from a CI perspective, all unit tests written by developers, at a minimum, are executed as a part of a build (although builds may be staged to run fast tests first followed by slower tests).