Forgive the reference to AD&D but I’ve just experienced a situation where my agility needed to be 17 or 18 (or maybe greater with some god-like intervention).
I’ve blogged before about how awesome TDD is. For those of you hoping I’ll recant those statements, I’m sorry to disappoint you. I just want to share some experiences with you.
We're developing an asp.net application, of course we’re doing it TDD with NUnit and NUnitAsp. To grossly simply the application and protect myself and clients it basically consists of two types of users (A and B), a whole bunch of input (which B is only allowed to edit) and processing (which only A is allowed to do). My test suite was complete and green until a few days ago. We introduced a concept we call “shadows”, wherein we make a copy of an instance of input for B1 and B2 (they each get their own copy) to edit so we can deal with some concurrency issues (there are still change resolution issues, but for now those aren’t important).
So after we could create the copy we had to implement it in the UI. Whenever B1 wanted to make a change he had to click on and “Edit” button, we’d create the shadow and then B1 could edit. Before writing the code I updated some tests (we have a header and that’s where I wanted to add the “Edit” button) and added the button. I wrote a test to make sure clicking edit redirected you back to where you were, only this time with the shadow so you could edit. Then I wrote the code to make the test pass.
At this point I ran the test suite, and just about every UI test for B users failed. They were checking [mostly] edit functionality that they expected to do in place. Well, obviously that’s not the case anymore, you have to click edit first and then get the shadow to edit. So I start running through the TestFixtures to clean them up, not a hard process, just long I probably broke a few hundred tests. Luckily I could just add a Click() and Assertion to most of my SetUp’s and be done with it. I couldn’t fix all my tests because that pesky “change processing” decision hadn’t been made yet.
Oh cool, another meeting. This time I find out, we’re probably going to skip this whole shadow/change processing idea because it’s implementation would slip schedule and budget. Keyword: probably. We won’t know until we get verification from the customer that this is okay. So here I sit with a mangled, beaten and brutally bruised test suite partially mended from my fixes before the meeting.
So do I go to green just to rip out all this functionality to cripple my suite again and go back to green before continuing on with other functionality? TDD purists would say yes. Anyone involved with paying me to do this work, to undo this work, to repeat this work to actually start new work (did you follow all that?) is probably going to balk at that idea. I could have rolled back the source to the point where I checked in Shadow Complete and before I integrated it into the UI, then my code and tests would all be where I hope to be when the customer says accepts these changes. Only I can’t rollback without the customers approval. I could branch the code to continue working on some unrelated features then try to merge against an older version or current version depending on the customers decision.
In the end I decided to ignore the problem. There is enough work to be done in the business layer that doesn’t affect the UI that I can continue to do until that decision gets made (should be any minute, which is why having an on-site customer is a tenant of XP, one we’re currently not following). Then after the decision gets made I might have to rip out some functionality, but either way I’ll be able to get the suite back to green. I apologize to the purists, and I’d love to know who’s paying your mortgage, but as a consultant it’s hard to waste the customers money to conform to the letter instead of the spirit of TDD, especially when this customer has embraced TDD and other Agile practices and is up against schedule and budget constraints. Before you talk to me about limiting scope, we are, this is just an odd situation.