Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Test Driven Development Andrew Rendell Valtech


Published on

Test Driven Development has long been a key tool in the agile toolbox. Often it is suggested that the technique has moved into the mainstream.... Having worked with TDD for the last five years with varying degrees of rigor and success I have observed that effective application of TDD is

This paper takes a pragmatic approach in
evaluating the implementation of, impediments against and measurable benefits of TDD on a large, commercially successful, project. Analysis of this
experience will show how and why TDD is being used incorrectly and how this situation can be corrected.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Test Driven Development Andrew Rendell Valtech

  1. 1. Effective and Pragmatic Test Driven Development Andrew Rendell Valtech Abstract Test Driven Development has long been a key tool required to run under significant load twenty four in the agile toolbox. Often it is suggested that the hours a day, every day of the year. technique has moved into the mainstream and that not Unlike previous incarnations of the mobile internet applying a test first approach is exceptional. Recent portal at T-Mobile, the Web’n’walk-3 home page coverage in the community has even started to could be personalized. Customers could add widgets describe a post-TDD approach. Having worked with which displayed their favorite content. A variety of TDD for the last five years with varying degrees of widgets providing everything from news to email rigor and success I have observed that far from being clients existed. ubiquitous, effective application of TDD is From October 2007 the Web’n’walk-3 application uncommon. was live in a number of European countries. This paper takes a pragmatic approach in T-Mobile is very customer focused. As an evaluating the implementation of, impediments organization it prides itself on the stability and against and measurable benefits of TDD on a large, scalability of the systems providing customer services. commercially successful, project. Analysis of this This encourages its development organizations to be experience will show how and why TDD is being used conservative and employ very careful management of incorrectly and how this situation can be corrected. risk. At the same time the mobile telephony market is The analysis will show how project delivery improved one of the most competitive in the world of when a more effective approach was applied. telecommunications. This puts development groups under pressure to respond quickly to stay on the cutting edge. 1. Introduction These conflicting requirements of risk aversion and rapid adaptability create an interesting software This experience report details the application of development dynamic. Valtech believes that agile, Test Driven Development on construction of the and in particular Test Driven Development can help Web’n’walk-3 mobile internet portal at T-Mobile these companies deliver quickly and safely. International in the UK. In the summer of 2007 the marketing organization T-Mobile International is of one of the largest within T-Mobile set their development teams a mobile companies in the world, a major branch of challenge: To build a new mobile internet portal Deutsche Telekom AG whose subsidiaries and which incorporated the latest Web2.0 experience affiliated companies serve over 86 million mobile where possible but still delivered carrier grade quality. customers worldwide. The marketing team set an exact date and time for Web’n’walk-3 was the mobile internet portal for launch several months in the future. The timescales T-Mobile customers. When a customer pressed the were much tighter than for previous projects and internet button on their phone, the Web’n’walk-3 initially some doubted it was achievable. This home page was to be displayed. This mandated that experience report details the small part that a fairly the page be delivered as quickly as possible and the successful application of TDD helped in delivery of application had to support a large number of that goal, on time. concurrent requests. The Web’n’walk-3 portal was
  2. 2. 2. Introduction of TDD modules. This class implemented a number of methods. Each method returned a model object in a state that corresponded to a scenario in the use cases. When a project is initiated how does it become ‘test driven’? In common with many other projects the For example, development of the email widget involved Web’n’walk-3 application was not immediately the view and the server side developers sitting together and identified as one that would be using TDD. At the creating a class with the following signature. This figure has point TDD was first considered, the project had been been slightly revised for commercial and readability running for several weeks and created a sizable body reasons. of prototype code. There were some JUnit tests but EmailWidgetModel XXXEmailContract these lacked structure and there was no common +customerNotAuthenticatedWithPartner() : EmailWidgetModel approach (or even clear intent) to achieve high +oneReadOneUnreadEmail() : EmailWidetModel +noUnreadEmailFiveReadEmail() : EmailWidgetModel coverage. As the project transitioned from elaboration +noEmail() : EmailWidgetModel +manyEmails() : EmailWidgetModel into a construction phase various new team members +errorGettingEmail() : EmailWidgetModel were brought on board who identified that a TDD approach should be employed. Immediately upon XXXEmailAcceptanceTest making this decision, the technical architect used the JUnit4 test Cobertura code coverage tool to identify that test coverage was very low and in several modules, non- existent. XXXEmailWidgetService 2.1 Communicating the intent Figure 1: Contracts and Acceptance tests. It was communicated to the developers that a test Part of the infrastructure developed by the team allowed first approach was to be employed. As has been the the view developer to execute the methods in the contract case on previous projects in my experience there was class. This injected the model object returned into the view universal approval from the programmers for this under development. The view developer could then decision. Programmers still consider TDD a cool progress with the complex task of building the UI for all the technique and one worth adding to their repertoire. use case scenarios with no further dependency on the server The team held a number of white board sessions side developer. where the mechanics of TDD were discussed. The The server side developer then created one JUnit test for technical architect felt that although several team every method in the contract class. members were inexperienced in this area and would For example, the figure above details a contract class make mistakes they did on the whole understand the with the method 'customerNotAuthenticatedWithPartner'. objective of using TDD and the implementation The 'XXXEmailAcceptanceTest' class contains a test details. 'testCustomerNotAuthenticatedWithPartner'. The xml response from the email provider indicating non- 2.2 Enforce TDD through application authentication would be added to the behavior of a mock structure HTTP client. All other configuration data, such as customer database rows, would also be created. The architecture of the Web’n’walk-3 application The system is then in a state where the model object was essentially Model View Controller. The returned from a call to application should match the model complexities of rendering the portal on mobile object returned by the above contract class method. The browsers were encapsulated within the view. All other JUnit test executes this call and asserts that the resulting functions such as customer identification, integration model objects are equal. At this point the acceptance test for with downstream partners and enabling systems etc. this particular scenario has passed. These tests run against a were encapsulated in a set of server side modules. The full application stack inside a Spring container. Only calls interface between the views and the server side to external systems are stubbed. modules were the model objects. The contract class above has become the test first The realization of a widget presented to a definition of what is to be delivered. It is unambiguous and customer included a set of views and a set of server easy to understand. The sprint backlog was prioritized so side modules. The first activity in development of that that creation of this contract was the first activity addressed. widget was the creation of a contract class intended to The last item on the backlog for the use case was the capture the expected output of the server side successful execution of the entire acceptance test. This was
  3. 3. the measure by which the use case is deemed Often they made mistakes (see below) but then identified ‘completed’ by the developer. and learned from those mistakes and went on to refine their In summary, the use of TDD was encouraged by: technique. There were a limited number of developers who did not respond positively to the experience. The sequence • Making a clear statement that TDD was to be of events many developers experienced when adopting used; TDD are listed here: • Encouraging practical team discussions about the benefits and implementation; 1. Start using TDD and writing tests at the same time or before writing code. • Using the Cobertura code coverage tool to 2. Possibly spend too long writing tests and get regularly measure overall coverage and consumed in applying the approach dogmatically. identify ‘hot spots’ of non-compliance; 3. Start to slip on the burndown and experience the • Mandating a development approach which at pressure of having a velocity markedly lower than the very least guaranteed that development that of their peers. would always begin (and hopefully continue) 4. Find that refactoring work is taking longer than they with a test; expected because poor code structure has lead to a large volume of fragile test code which also needs 2.3 Degree of freedom in application of the refactoring. technique 5. Start to comment out tests or mark them with @Ignore. One of the most refreshing aspects of working in 6. Stop writing tests at all or vastly reduce the number an agile team is the focus on practicality and of tests in place before code is checked in. Attempt empowerment of the programmers. Whilst TDD had to write the tests last because the code can be obvious benefits, the architect did not want to impose considered ‘complete’ in their SCRUM report a regime that developers would either apply without the test (i.e. it can be used and nobody will dogmatically or felt coerced into using at the expense immediately notice the poor coverage). of their own creativity. Therefore TDD was the 7. Fail to catch up with retrofitting tests. preferred development approach but it was not 8. End up with large areas of code without any testing mandated. Developers were discouraged from writing which would take far too long to retrospectively code before writing tests (other than the acceptance write tests for. tests above), but it was not seen as a ‘serious’ offence Most practitioners on our project made some or all of not to do so. these mistakes. Even our best developers experienced Empowering developers did occasionally result in events 1 through 4 in the first few iterations of a reduction of quality (described in the next section). development. Efforts were made to identify developers who Upon reflection, high test coverage, whether it was were falling into these traps as early as possible and provide achieved through unit or integration tests, should have them with help. Often this was as simple as insisting that been nonnegotiable. A developer could be brilliant they revisit their estimates for work. enough that they produce low defect, well structured Developers who came away from the project with a code without coding a test first. This does not help negative view of TDD were those who went through all the subsequent, possibly less able, developers maintain above stages and still failed to correct their behavior. that same code without the support of high test In many cases those developers had been seen as very coverage. successful on other, non-TDD, projects. They had been held in high regard by their peers and managers. Their 3. Pitfalls in implementing TDD perception was that they had a strong record of delivery until they were forced to use TDD. 3.1 Disillusionment Burndown charts and the use of acceptance tests as the definition of completeness gave a clear measure of progress After initial enthusiasm, developers can come to on Web’n’walk-3. On the negative developer's previous resent TDD as they perceive it as being a technique non-agile projects successful delivery may have been more which reduces their efficiency. This is especially true subjective. These developers now perceived themselves to when burndown charts and measurement of velocity be under far greater scrutiny through the burndown charts. are introduced at the same time as TDD. They also noted that instead of just cutting code, as they The majority of developers involved with the would have previously, they had to spend development time Web’n’walk-3 project were new to TDD. Most started writing tests. Their (incorrect) conclusion was that it was with enthusiasm and applied the approach with vigor. the application of TDD which was responsible for their lack
  4. 4. of success and acclaim on the new project. In my into a form for the Web’n’walk-3view. It was this area of opinion, this was a major factor in those developers complexity that required particularly rigorous testing and is disillusionment with TDD. the subject of this example. As development progressed, requirements were refined 3.2 Dogmatic application and defects were reported. This led to a number of updates to the code. As the class diagram (amended for commercial Dogmatic application, especially common to new and readability reasons) shows, the structure of the module practitioner, leads to increased costs without a degraded. The logic which implemented the transformation corresponding return on investment. of data was implemented in three different locations. (This During the initial development of Web’n’walk-3 should have been spotted by Greg no matter whether TDD the Cobertura tool revealed an unexpectedly uneven was being used or not). distribution of test coverage. Some modules had very Greg applied tests in a dogmatic fashion. It is likely that high levels of coverage in domain objects and less in he did not always write the test first but built them to test their services. Further investigation revealed that tests code he had just created. This meant he failed to recoup the had been written with the sole purpose of increasing structural benefits to his code that might have applied. It is code coverage without providing any additional value. worth noting that the code did have high test coverage, The most obvious of these were tests on the gettters which was useful in later refactoring. and setters of POJOs. Where tests would have been most valuable, in the complex business logic of the HttpClient Logic for implementation of transformation services, there was less coverage. implemented piecemeal in several classes Poor test coverage was more common in those classes whose construction did not enable straight forward test creation. More experienced developers AuctionWidgetModel WidgetService Worker XmlService simply redesigned the code to make it more testable when writing the test became onerous. In the majority of cases this led to better code. Tests Tests AuctionWidgetModelTest WorkerTest Occasionally this approach produced code that +testSelling() +testCombineWachingAndBuyingTotals() Tests was less elegant in some way that that of the developer’s initial implementation. In some cases this Logic for testing data inelegance took the form of slightly more lines of transformation implemented in XmlServiceTest several different classes code or possibly the removal of a novel new language +testWatchingData() feature. Our general approach was that it was better to Figure 2: Low cohesion have less elegant code if it could be tested with greater ease and the purpose of those tests was more obvious. When other developers came to correct defects caused by incorrect data transformation, they applied the TDD 4. Benefits approach. First they started with the data from the auction site that reproduced the defect. Then they looked for the test class in which to add the new test. It quickly became 4.1 Better cohesion obvious there was an issue as there was no single place to add the test. Instead two or sometimes three test classes had As practitioners gain experience of TDD their to be amended. This was an obvious ‘bad smell’. code quality increases. Classes become more cohesive and less tightly coupled. In the next release a backlog item was executed which called for the refactoring of this particular module. Using The example below describes how one particular the acceptance tests a second developer, Jo, started from the module was initially implemented with a dogmatic entry point to the system (the widget service in the above and less effective approach to TDD. It was then diagram) and worked down. Jo was very careful to ensure refactored using a more refined approach which that the tests classes were exercising a cohesive set of resulted in a much better code structure. functionality. Where a single test class performed very Greg, a developer, was new to TDD. He was different types of test this was a cue for the class under test tasked with the implementation of a module which to delegate functionality. This is classic O-O design which would fetch customer account data from an auction could have been achieved using many other techniques but site and deliver it to the Web’n’walk-3 view layer. TDD was found to be particularly methodical and rigorous. The module had a particular area of complexity, the transformation of the data from the auction site API
  5. 5. The construction of simple tests became a litmus would result in requests to different downstream systems. for cohesive code. The end result was a much cleaner Those requests had to be executed in parallel. Failure to do class structure where all the data transformations were so would have resulted in a page rendering time equal to the in a single, simple class. The tests which defined how sum of all downstream request latencies. The aim was only the propriety auction xml was interpreted were also to wait as long as the slowest request before completing a encapsulated in a single class. page. A series of whiteboard sessions were held and a The diagram below shows the revised class design by sketch was created. This parallelization structure after refactoring. infrastructure was built at the same time as the classes that would eventually use it. The final implementation of this infrastructure component did achieve what it was intended, All data transformation logic encapsulatred in XmlAdatpor. All tests and test data in XmlAdatporTest. but at a cost. It was difficult for client classes to use and contained many features that seemed 'useful' to the WidgetService Worker HttpClient developer but were never used in anger. A later refactoring exercise started development by building tests which were driven by the client classes. The resulting solution was far AuctionWidgetModel XmlAdaptor smaller, simpler to use and had less defects. Partly this was because the second time you do something you do it better. A great part of it was due to focusing on the real use rather than what was predicted. XmlAdaptorTest 4.3 Virtuous circle of agility Figure 3: High cohesion Solutions architects and business stakeholders quickly There were many other examples identified by the grasp that tests increase confidence of the functional developers of the top down approach from the correctness of a given area. This makes them more acceptance test leading to simpler classes with better confident in their support of other agile techniques such as cohesion. refactoring. This introduces a virtuous circle where code can be cut faster because developers know that they will be 4.2 TDD encourages YAGNI able to go back and optimize or add features later with management approval. It also means that the code base YouAintGoingToNeedIt as described in Ron stays dynamic and is less likely to be the subject of arbitrary Jefferies’ wiki posting with the same title [1] is a and all encompassing code freezes dictated by senior powerful tool when building software. If there is no managers attempting to reduce risk of instability. use for a particular feature, then it should not be built. The following is a powerful example of this virtuous This appears so obvious that it hardly needs stating circle: but far too often functionality is added speculatively, A new requirement emerged from the marketing team in especially when building infrastructure type libraries the area of customer identification. Detailed analysis of the for use by other parts of the system. user population showed that a particular mobile handset Driving development top down from the known to be in wide use but not thought to be popular for acceptance tests encouraged developers to apply the mobile internet was actually responsible for a significant YAGNI principle. They were naturally much less percentage of traffic on the network. The issue was that this likely to build that extra piece of cool code which particular handset had some very specific requirements turns out to be of limited benefit in meeting the user regarding the identification of the customer using it. goal. The code module responsible for identification was the Infrastructure components that might be used by most complex of any in the system. It contained a myriad of several different modules should be built in response business rules. It had dependencies on several downstream to a requirement identified by writing a class which enabling platforms. Customer identification is very requires that service. Building infrastructure important as it is obviously key to the operation of an components before building any users of those application whose market differentiator was a personalized components tends to lead to the YAGNI principle experience. being violated. Customer identification obviously has some critical It was obvious from the early stages of the project security requirements, especially when presenting possibly that some concurrency infrastructure was required. sensitive personal data such as emails. Protection of Aggregation of content for a customer’s home page customers’ data is very important to T-Mobile. To mitigate
  6. 6. the risk of an error in this part of the system detailed lack the necessary experience which allows them to utilize analysis had been performed by the development team it most effectively. and solution architects. State machines had been When developers do gain the necessary experience in formulated and captured in UML. These were then Test Driven Development and apply it pragmatically it does used to construct a large suite of manual tests that enhance the structure of code. were executed using a variety of handsets and radio Test Driven Development was not responsible for the networks by a very skilled tester. success of Web’n’walk-3. It was however, one of many Unfortunately at the point in the project where the important techniques applied by the team which allowed T- new requirement was identified the human test Mobile to achieve a higher degree of adaptability than had exercise had already been completed. A meeting was been exhibited by similar projects without sacrificing their called and attended by representatives of testing, commitment to carrier grade quality. solution architecture, program management and development. The mood was somber. Given the teams 6. References commitment to quality and the client’s aversion to risk in this area in particular it looked likely that [1] Jeffries R. , You’re NOT gonna need it! incorporating the requirement would be impossible without a slippage. This all changed when the solution architect made the following, critical, statement: “We must not forget this is a very different system to those we have gone live with in the past. We have an extensive array of automated tests that the developer built as part of the design and analysis of the identification component. Peter [the human tester] ran a very comprehensive test suite on this code and proved it was correct. The bugs that Peter found were fed back into Matt’s [the developer] JUnit tests. They all pass now. We can make this new change with a high degree of confidence that it won’t break the existing functionality. We have not had a server side system built like this in the past. It is a big step forward. We can do this.” The confidence that the TDD approach had given the solution architect enabled him to make this statement in an environment where carrier grade quality is jealously guarded. The change was made, the tests passed and this part of the system went live and continues to operate with a remarkable level of quality. The identification component had seventeen discrete states in its state machine. Its dependency graph included fourteen different spring beans. During testing only five defects were identified. After go live no defects were reported in what is possibly the most complex single part of the system. Four months after go live there was an update in the enabling platforms which changed the way the devices in question here were identified. This introduced complex new states that were previously un-testable outside of a mocked environment. No defects were reported. 5. Conclusions Test Driven Development appears to be a technique that many developers are very aware of but