In an agile team, things go fast. And when things go fast, it usually gets messy. But then, why agile teams have proven record of success?
An agile method is based on a set of values and principles that embrace and support each other. When one aspect of the philosophy looks like it’s not “formal” enough, another practice supports its weaknesses.
Environment
In order to stay focused on the task at hand, an agile team will have to setup its environment to make sure everything runs smoothly. They will create unit tests and make sure they get the green light prior to a check-in; but that’s usually not enough. They need to make sure it works on their machine and that it can work on any other box matching the requirements.Those requirements represent the environment the software needs to live in to run smoothly (or at all). It will vary but can usually include:
- A specific version of the runtime
- Third party assemblies deployed (locally or in the gac)
- Configuration files at different URIs (ideally relative)
- Environment variables
- WMI schema registered
- Registry entries
Continuous Integration
An many variables come into play, we need to make sure that for a given set of values, the software always works the same. In order to do so, agile teams will setup a clean environment (build server), seal it and automatically test that whatever changes in the software, it will continue to run on this environment. That’s what continuous integration (CI) is all about: continuously integrating the latest changes into a given environment and automatically checking that it installs correctly, that it runs as expected.
Contamination
Why isn’t the dev environment clean enough? Because we all know many things are going on and aren’t ideal on a dev box:
- A newer version of a component is installed to test out features we might need in the future
- A beta is installed and then uninstalled (partially)
- Registry entries get deleted or manually added
- Parallel versions are running
- Debug versions are running
- Bits exist locally but aren’t in sync with source control (think Lib folder)
Those are all reasons why it might “work on your machine” but not on “every machine”. Choose your side.
Long and External
When code changes, it might break existing assumption. Agile teams will try to document those assumptions in some executable format, usually unit tests. But not all tests are born equal. Some are bigger and broader that simple units. Some are testing the integration, the system and the use case as a whole. Should a developer wait for every single test to pass when he changes a string.Format() argument before he commits the change back to the repository? Ideally yes. But that’s not ideal; he might end up having to wait for a while for those exhaustive tests to pass (or will they?).
When you have a CI mechanism with a dedicated build machine; the whole suite of tests will automatically run in the background when something changes in the source code repository. While the developer continue working on new problems, he will get notified if something broke the build. The context the breaking change was made in has still not totally dissipated and it is easy to figure out what went wrong.
A long running test is one thing, but what about external tests? Some other teams might have some dependencies on your code. Some other projects of your own might have some dependencies on these modified bits? What then? Well they should also be part of the CI build so that they too can receive quick feedback that something is going wrong.
Tools
There are many tools to help you with CI. Cruise Control .net is one of the most popular. CI factory is a facade over CC.net that eases the configuration process.
Process
CI should be put in place as soon as possible; usually during Sprint 0 so that the team is up and running for Sprint 1 and leverage the short feedback loop quickly. A good enough CI environment can usually be setup in less than a day.
But what if it fails? What if it fails between the new tests have been committed and they don’t make sense? What if code shows a flaw in the acceptance criteria? What if you have a dedicated test team as opposed to a truly cross-functional dev team? That’s where things get interesting.
There’s no absolute truth to this one. However, depending on the type of test that failed (integrated or unit), it might end up being the dedicated test team that lives on the front line, assesses the bug and then informs the dev team that something went wrong.
() => “Francois”