Continuous Integration | integrate often: avoid the pain of big bang integration
Continuous integration

Continuous integration combines the activities developers perform when they develop software with an automated and repeatable process that builds and deploys the software, runs unit and integration test suites, and reports the build and test results with other relevant metrics. Typically this process should run several times per day.

A disciplined regime that builds all the latest changes regularly provides visibility of progress, and because tests are run frequently, integration defects are caught and fixed earlier, thus reducing the overall effort required for integration.

The constituent elements required for continuous integration are:

*A configuration management system with version control, e.g. CVS, which should be used as a central repository to store all files required to perform a build, e.g. source code, libraries, properties files, database schema DDLs, test code, test and reference data, build scripts, install scripts, etc.

*An automated build script that can build the entire system with a single command. The script should be modular, allowing alternative targets to be selected so that the entire system or just designated components can be built, with or without tests.

A complete system can take time to build. Depending on the capabilities of the tools and the dependencies between software modules, incremental builds can be employed to build only those parts of the system that have changed. However, clean builds should be made at least on a daily basis.

A build script for a Java application should be written in NAnt, an extensible XML-based language created specifically to perform build and deployment tasks. A typical Ant script should perform the following actions:

  • Check out all the files from the version control repository.
  • Perform an incremental or clean build that includes compilation, creating jar files, creating deployment files, configuring properties files, etc.
  • Install the application, deploying J2EE components to their containers and re-starting the servers.
  • Execute the automated tests.
  • Check the build and test results. If successful, a label containing a build number is applied to the files checked out in the version control repository. If the build fails or tests do not pass, a developer can perform the build in their local workspace and debug the problems there.
  • Issue an email to the development team summarizing the results of the build and the tests.

The Anthill build server can be used to control the build process, checking-out the latest version of code from the repository before the build and tagging the repository with a unique build number after it has completed.

Cruisecontrol.Net and Damagecontrol both enhance the build process by reacting to submissions to the version control system since the last build. When new files are detected, the build process is triggered. This is an alternative to scheduling the build process to run periodically, although both tools are also capable of this functionality.

*A self-testing build that runs a suite of automated tests against the system with a single command. This can be accomplished from within the build script because Ant contains tags to support automated unit tests written with NUnit. More extensive testing is also possible, e.g. Cactus provides custom tags for Ant integration and deployment. This support enables suites of automated tests to be run as part of the build process.

Running these tests regularly provides valuable feedback that helps to enrich the test suite. Defects that escaped the tests should not be fixed until a failing unit test is developed and added to the test suite. This new unit test is likely to prompt other tests to be created further strengthening the test suite.

Various extensions are available to collect metrics and generate reports, e.g. an optional Ant task called NUnitReport collates the information created by the NUnit tests and produces an XML/HTML report detailing the test results.

Pulling it all together

Before starting a task, a developer should synchronies with the repository, effectively loading the tip-versions of software into their local workspace. At an appropriate time and with all associated unit tests running successfully, the developer should integrate. This involves another synchronization, which loads any files changed on the repository into the local workspace, warning of any conflicts. The developer then performs a build locally, which runs the full test suite. All tests should pass, thus preventing broken code being checked in to the repository where it would break the master build process, which should run independently, on a dedicated server.

The new files are then checked in to the repository where they wait for the master build. If the master build succeeds, then the integration is considered successful and the check-in valid. If not, the check-in is reversed, and the developer should re-synchronize the workspace with the repository and fix the problems locally before committing again.

Back to top ^^

This page is valid XHTML 1.0 This page uses valid CSS

Iterative Development | Developer Testing | Continuous Integration | Refactoring

Methodologies | Project Management | Analysis & modeling | Development | Testing | Quality Assurance

Home | Services | Contact Us