In recent posts I have written much about
testing as an inherent component of the software development process – the last one, for example, was devoted to some drawbacks of having tests. Now, to
keep things in balance I will turn to an advantage of TDD which I happen to mention
much less frequently than it deserves.
When writing tests I do search for such things
as confidence, correctness of code, guidance for better design and description
of the software components and their invariants – all the things that I come
back to in each and every post about tests. As I wrote a couple of weeks ago,
with all this I get some inertia and a chance of falling into the trap of
overestimating the quality and bugproofness of my programs for free. Still,
tests give me one more gift, which is sometimes more valuable than all other
benefits and compensates for many drawbacks: tests make me focus on doing
precisely what I need to do at a particular moment and think solely about it.
Put another way, they allow to work on features one at a
time, ignoring most of the context until the current portion of work is finished. This
undoubtedly positive narrowing of scope is done in two ways – passive and
active, if you wish.
To begin with, if one uses the tests-first
approach, each unit test, once it is created, acts to draw developer’s attention
to a certain small piece of functionality – the piece that is desired, but
missing at the moment. When you strive to make a test pass, the red light does
its best to help you focus on solving this particular problem. In fact, if you
are disciplined enough to start writing tests, you are also most likely disciplined
enough to devote all your efforts to making the single test go green, instead
of going elsewhere and hacking code that does something valuable though
irrelevant at current stage.
Beside the annoying red light that obliges a
programmer to do what it wants, there is another thing to unit tests that helps one
to concentrate. It is difficult to clearly separate this from all the benefits
that I usually mention, but tests make the task of starting a component or even
the entire project much easier. From my perspective, that happens because of the combination of two causes. First, to make up even a single good
test you have to chunk your work explicitly. The act of fulfilling this requirement
has a well-known name – that’s simply planning. This said, when laying out a
test-suite one actually writes a plan of a particular unit of their program
providing themselves with two key components of every plan: explicitly named
goals and the means to know when one is done with them. Everyone who has tried
to create a schedule for a week at least once knows for sure that plans hold
much value and large part of it comes from availability of a carefully laid list of
tasks, which draws one's attention to their goals and helps a lot to focus on them. Let me repeat it
once more: tests are your plan, roadmap showing where your program can be
driven.
Another reason that makes programming with
tests easier is that, in my opinion, composing test cases is often less
difficult than implementing actual components. Since tests play the role of usage
scenarios their idea might be clearer than the details of how certain goals
should be achieved – at the beginning we usually understand what we want from
our programs better than what should be under their hood. This way, tests written
by a programmer actively help him or her focus on development. However, that’s
only the active part of the story.
The idea behind the passive influence of
testing on programmer’s concentration is actually much clearer and boils down
to a single word – regression. As we know the key purpose of regression testing
is to verify that new code doesn’t break the existing functionality. More
accurately, when regression tests are run they automatically check that certain
assumptions about the system still hold despite the arrival of new chunks of
code. This ability to know when you have stepped the wrong path and broken
something is important enough by itself, but what makes it even more valuable is
the fact that it frees you from worrying too much about the possible far
fetching impact of the fresh code that you commit. The attempts to foresee the
surprises, which a minor change in the existing code can bring, take a lot of
mental effort and make it very difficult to focus solely on working to your current
goal. Our mind is powerful, but it doesn’t allow to concentrate on several things
at once, so it is quite good to be able not to think of possible harm until we actually commit a crime. The hard work we put into our test-suites
pays back allowing us to do this harm safely so that it is OK to pay attention
only to those things, which are important at the moment, ignoring most of the context.
Don't get me wrong, I am far from stating here that having tests
you should not think of potential errors that you don’t catch and only hack
more and more code because tests protect you. Continuing the analogy with
planning, even if you have a schedule for a week you have to step back from
time to time and see how it fits into the greater picture and how good are you
at drawing it. My suggestion about concentration is not based on the
presumption of the ability to foresee everything either – even with tests we
give birth to dozens of bugs. Nevertheless, when choosing the path of
test-driven development you adopt the stance of not worrying about the mistakes
that your tests don’t catch until you find yourself in the green zone. Once
there, you are free to pick the next goal: check if your idea about some
bug is correct or start a new component – in both cases this basically means
picking a name and location for a new test. At the same time, while the lights
are red you should be kind of hypnotized and focused solely on the actual
portion of work required to satisfy them. Fortunately, there is some strange power
to everything red – even bulls can’t resist the temptation to get rid of it.
As for me, I have come to believe that what
makes me test-drive programs is not the desire to be confident in their
correctness – I can never be 100% sure – or the plain idea that I will spot a
bug or two long before launching the program for the first time. Instead, I
must be simply following the most comfortable road, because tests allow me to
concentrate on my goals and enter the praised state of ‘flow’ easily. Furthermore,
if I leave one red for a night, I will be able to get back to work with minimal effort next morning.
As a bonus here is a number of worthy articles devoted to different aspects of testing, which I spotted in my feed this week:
- Refactoring Without Good Tests - Code Climate Blog
- A Better Syntax For Unit Tests - Andrew Binstock, Dr. Dobb's
- Agile Moments, "Why We Test" Edition - Eugene Wallingford, UNI
And as usual, I will appreciate any feedback: a piece of advice, an angry comment or anything else!
Комментариев нет:
Отправить комментарий