07 Mar 2015 by dryobates
In perfect programming world requirements doesn't change. We don't live in perfect world so how Test Driven Development can help us when requirements change just before a release?
Last week I had a talk about Test Driven Development and Coding Dojo on PyStok. PyStok is Python Users Group run in Bialystok.  One question that I’ve got was how to deal with requirements change using TDD. I think that’s interesting question and I would like to answer it in full here.
There is one common myth about TDD that lies in some programmers mind. Myth says that when requirements change then all that you have done before became useless. Especially test become useless. That’s wrong.
Let us first consider what would you do if you won’t use TDD for development. Let us say that we have N functionalities. We have finished all of them. We still have 20% of contracted time so we will add some test. Then customer says that he would like to change some functionality. What would you do? You would dig into code trying to change that functionality and praying not to broke others.
If you’re lucky you’ll make requested change in that rest 20% of time and won’t break other functionalities. You would rather not manage to add the tests you have planed. Changing or extending anything in future at some point became a nightmare without tests.
If you’re not lucky at all, deadline will pass, you’ll still have not finished requested change and broke other functionalities. Nothing to release :(
Test Driven Development approach
Now what would happened if you use Test Driven Development? On my talk on PyStok I proposed Double Loop method for use with TDD. So first in short let’s look how it works.
First you take some User Story and write BDD-like  test scenario (you don’t have to but it helps a lot).
Then you analyze what objects are used in that story and build some general object model. It can be helpful to use some tool like CRC cards.  Then you write acceptance test based on on that scenario and object model.
Next you choose some class, analyze it’s responsibilities and write a list of tests that it should pass.
Then goes traditional TDD: write test code, write production code, refactor and start with new test. When you finish with one class analyze next class and so on. When you finish with one story go for next.
Now let’s back to our main problem: What to do if requirement has changed? Again, let’s say that we have N functionalities. We have finished 80% of them and 20% of them we plan to finish in the last 20% of time. Of course we already have 100% tests coverage for that part which we finished thanks to TDD.
If change in requirement is in that functionalities that we didn’t touch yet it doesn’t hurt as at all (OK, completely separate functionalities are rare, but it still shouldn’t hurt us much). What if change is in functionality that we already implemented?
- Modify test scenario based on change in user story.
- Modify acceptance test based on that scenario. Probably only part of it is wrong.
- Check if object model has changed.
- If some new classes appeared then code them with TDD as before.
- If some classes became useless remove them and their tests.
- Modify unit test if that’s required and fix code so that all tests pass.
That’s all! You won’t break other functionality as you have valid tests for them. You still have 100% tests coverage. If you don’t then check that uncovered code. One of two things has happened: you didn’t write tests correctly and miss something or that code isn’t used at all and you can safely remove it.
Again, if you’re lucky you’ll change requested functionality and manage to finish rest of functionalities. If you’re not so lucky you won’t finish some of the last functionalities. But you use planning game, right?  So the last functionalities are less important then the first ones you have done. You still have fully functioning product with some less important functionalities. You can add them in next release or negotiate moving release date ;) I think it’s still better then having totally broken project.
Test Driven Development isn’t complete remedy for change in requirements but is essential for coping with it. All agile methodologies use TDD and tries to make a change in requirements natural part of process rather then thinking of it as unusual exception that breaks everything.
|||PyStok https://www.facebook.com/PyStok (in polish)|
|||BDD = Behaviour Driven Development https://en.wikipedia.org/wiki/Behavior-driven_development#Behavioural_specifications|
|||Class Responsibility Collaboration card https://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card|
|||Planning game https://en.wikipedia.org/wiki/Planning_game|