Recently I had an interesting buzz conversation with a former work-mate, Peter. Just like myself he heavily orientates his learning to best practices, especially into agile software development methodologies and automated testing.
I was doing a refactoring session, modifying a huge part of the core logic of my Android app which I'm currently writing as a part of my MSc thesis and after succeeding I published the following message on
Twitter:
just #refactored application critical core logic. Would have been totally impossible without #unittest
Consequently Peter reacted, asking me about whether I would say that
TDD tests are unit tests? His question made me think...actually I never posed a similar one to myself. From a pure theory point of view I'd say
"not necessarily" which was also my first answer to him.
Unit tests are supposed to test a
single unit
in isolation.
TDD - which is usually referred to as
Test
Driven
Development although I personally prefer
Test
Driven
Design which in my opinion captures its meaning in a more precise way - tests are not said to necessarily cover a
single unit. They are meant to
drive your design s.t. it becomes incrementally (like Kent Beck calls it in his
Extreme Programming Explained),
evolving (evolutionary as by Fowler). So in theory they may also cover multiple units.
Do we really need to be so strict?
When working on my Android app I proceed in a TDD way. There are days where I don't even touch the emulator but rather I do quick test->implement->test cycles which give me all the feedback I need till then comes the point of integrating everything where I will use the emulator to verify everything and deploy it also on real devices.
I also do write unit tests, taking my unit out of its context, verifying its correctness in isolation. But hey, I never ever worried about whether I was writing "unit" tests or "TDD tests". Sure, some of my TDD tests are pure unit tests and others cover 2-3 units maybe, but I've always seen the unit testing framework as the tool and TDD the methodology. Do we need to be so strict about this difference? Would it change the way we write the tests during development??
What really matters!!
Theory is important for learning. People need to understand the differences and it is clear that we have to highlight and express them. But ultimately what counts when working with automated tests is feedback. Those automated tests are so valuable during development because they give you a feedback, like customers will give you when you show them your app. This motivates and shows you're on the right path during development.
Then there is regression testing. Nobody is perfect and so you always again run into sub-optimal situations during development. But do you have the courage to refactor and make it better? How will you be able to know you didn't break anything else? IMHO serious refactoring cannot be done without a substantial suite of automated tests (your regression testing suite) which has an acceptable code coverage.
TDD is so important because it will definitely improve your design [1], [2] and more importantly it is a test-first approach. As mentioned, code coverage is important for being able to trust your tests. With a test-last approach, first you just won't be able to reach such a high code coverage as in a test-first scenario and secondly writing tests after will result in much more pain and effort.
What you should distinguish is between those tests that have to pass in every imaginable state of your app (usually unit tests) and those which potentially may fail or take a bit longer to succeed (typically integration tests where you access the file system, network resources, DBs...).
[1] D.S. Janzen and H. Saiedian. Does Test-Driven Development Really Improve Software Design Quality? IEEE Software, 25(2):77–83, 2008.
[2] L. Crispin. Driving Software Quality: How Test-Driven Development Impacts Software Quality. IEEE Software, 23(6):70–71, 2006.
Questions? Thoughts? Hit me up
on Twitter