|
A hallmark of truly agile teams is an unquenchable desire to continually find new and better ways of developing software. These teams believe that there really are no "best" practices, only practices which work better or worse for them. This line of thinking is even apparent in the first line of the agile manifesto stating "we are uncovering better ways of developing". Notice the progenitors of the manifesto didn't propose that they had discovered the best way, only better ways. In this article I will explore two of the most widely accepted agile development practices, Test Driven Development and Continuous Integration, and question how these practices can be made better. I will examine their strengths, shortcomings, and how the ideas behind continuous testing can provide better and faster feedback on the health of a code base. While this article will illustrate with examples from the Infinitest tool, it will will also point out the other common continuous testing tools and categorize their underlying strategies as well. After reading this article you will be grounded in the ideas of continuous testing and ready to select a tool and apply this practice on your own projects. Current State CI is a technique whereby an automated build for a project is run after check-in, at some pre-defined interval, or a combination of both. Because all the tests for a project are typically run at some interval the test coverage provided by this practice is complete and the development team will all be aware of any unintended breakages. Although CI offers more complete coverage then TDD, the time it takes to get feedback is much greater [AE1] with developers receiving results at best a few minutes after a set of changes is checked in. Both TDD and CI are based upon the principle that feedback is good, and the quicker the feedback the better. With CI feedback is typically provided to developers no sooner than the moment of check-in. With TDD, feedback is provided for the tests manually run by the developer between every TDD cycle. And as previously mentioned, the quicker feedback of TDD is provided at the expense of more complete test coverage around any given change. So the question to ask in the spirit of continuous improvement is, "How can we improve on these practices by continuing to reduce the feedback loop while increasing the relevant coverage of our tests?" Continuous Testing Since the goal of CT is to provide rapid feedback for every change, and since changes could likely be happening rapidly as well, CT tools need to be smart about which tests to run in what order in response to any given change. This is because running all tests for a project might be quite lengthy. Although this would provide maximal coverage, it wouldn't provide sufficient rapid feedback to be any improvement over traditional CI. Different CT tools provide different mechanisms for handling this, as will be discussed later in this article. But for the moment, let's consider the approach taken by Infinitest, a Java CT tool. Infinitest uses a byte-code dependency analysis technique to identify the subset of tests most likely to be affected in response to any given change. For example, consider the related classes illustrated in Figure 1 below:
Figure 1. FooTest and BarTest each exercise a class under test which in turn depend on other classes in the system under test For any given change Infinitest will traverse all nodes affected by the change and collect all the nodes which it can identify as being test cases. These tests are re-run by the infinitest test runner and the results displayed within the developer's IDE. In this case, changes to the Fub class cause the FooTest to be re-run.
In this manner Infinitest quickly identifies the smallest sub-set of tests that need to be re-run and displays the results immediately to the developer without interrupting the development workflow. Figure 2 shows how the Infinitest presents the results within the IntelliJ IDE. Figure 2. Infinitest is continuously running tests affected by code changes in the background, providing developers timely feedback throughout the development process
Slow Tests
Figure 3. Well tested applications will usually have automated tests which run against the system under test at various levels of abstraction CT tools don't know or care about whether your tests are unit or integration tests. Rather they work most effectively with fast tests regardless of classification as illustrated in Figure 4.
Figure 4. The tests from Figure 3 are reclassified as fast tests and slow tests with lighter shaded tests being slow running tests while darker shaded tests are fast running tests. Notice that tests are classified as fast or slow regardless of test type, i.e. some unit tests are slow while some system tests are fast Infinitest in particular allows developers to exclude slow tests from the CT monitoring process through. In the future the Infinitest team hopes to automate the identification of slow running tests dynamically through the continuous testing process and exclude them from future test runs. Because CT is not (yet at least) a complete replacement for CI, developers will still want to execute the project's build before checking in, and still include the full suite of tests in CI runs. While not replacing CI, CT gives developers as much feedback as rapidly as possible. Developers see the results of their changes as they are made rather then only when they run a manual build, or when check in their changes and the CI server runs one or more configurations of tests against the new state of the code base.
CT tools also facilitate rapid feedback by allowing the test preemption and prioritization. After a developer makes a change, affected tests will begin running in the background and feedback is presented in real-time to the developer who is free to continue developing. If the developer completes another change before the previous test run completes, it is preempted and a new test run kicked off. Also, Infinitest optimizes the feedback provided to the developer by running tests which previously failed before tests which were previously passing. Figure 5. Infinitest presenting an error immediately after compilation
At this point in the TDD process the developer writes just enough code to make the test pass causing Infinitest to rerun affected tests and report that all tests are now passing as shown in Figure 6. Figure 6. Infinitest reruns affected tests, and in this case shows that all tests are now passing In this way Infinitest specifically, and CT tools in general, facilitate the TDD workflow by providing rapid Red/Green feedback without the developer having to shift focus and run tests manually. CT tools will also run more tests in each cycle than a developer, who typically only re-runs the current test which is driving the code changes. CT Tools Overview
Table 1. Available CT toolss Although the primary differentiator between these tools is the language they each support, they also vary in the strategy they employ to identify which tests need to be run in response to any given change. As illustrated earlier, Infinitest employs byte-code level dependency analysis to make this determination. Alternatives include analysis based on source files, conventions, project metadata, and the running of all tests in response to any change. These strategies are sometimes augmented with test prioritization to provide the most meaningful feedback fist. About the Author Trackback(0)Comments (2)
|
|||||||||||||||||||||
| Last Updated on Tuesday, 23 June 2009 19:18 |
Agile Marketplace - Announcements and Special Offers
Upcoming Webcasts
Sponsored by Urbancode - On Demand
Mastering Complex Application Deployment
Sponsored by CollabNet - Wednesday, August 24, 2011
Closing the Agile Loop: Continuous Integration, Continuous Information
ScrumWorks Pro – The World’s Best Agile Project Management Tool
Simply put, CollabNet’s ScrumWorks Pro is the best Agile project management solution on the market, bar none. More than 150,000 Agile professionals rely on the power and simplicity of ScrumWorks every day. But don’t take our word for it – try it yourself for free. CollabNet is now providing the first 10 users of ScrumWorks Pro at no charge!
Download ScrumWorks Pro today!
The Business Case for ALM Transformation
Are legacy systems holding your company back? Breakthrough these technical constraints with an open and scalable environment that meets your unique business need to transform. There is no reason to be locked into an obsolete platform. The output of a number of recent transitions from legacy systems, this is practical white paper shares lessons learned and illustrates how guidance and enablement can pave the way for change.
Download this Whitepaper


A hallmark of truly agile teams is an unquenchable desire to continually find new and better ways of developing software. These teams believe that there really are no "best" practices, only practices which work better or worse for them. This line of thinking is even apparent in the first line of the agile manifesto stating "we are uncovering better ways of developing". Notice the progenitors of the manifesto didn't propose that they had discovered the best way, only better ways. 







Fantastic article. I see a lot of value and uses in CT. I assume that InifiniTest right now uses JUnit under the hood to run the actual test cases. Is support for TestNG planned in a future version? It would be nice.
With support for TestNG, you could use notion of "test groups" within TestNG to mark your test cases as "slow" or "fast". TestNG (and the CT Tool) can then be told to just run "fast" test cases after every code change. Within the "fast" test cases, you will still analyze bytecode of the class to figure out what relevant "fast" test cases to run following a code change.
Cheers.