ArticleS. TimOttinger.
EverythingInItsPlace [add child]

Everything In Its Place.


Cognitive dissonance is so painful, or else I'm too sensitive. I'm not sure. In
my test-first evolution, I want everything to be tested, even those things done
normally in a GUI. I want an AT for every high-level policy and behavior. I
want little bitty unit tests for all the small behaviors.

However, I find methods inside the app whose only purpose is to respond to a
method in a test. There is no legitimate need inside that part of the system
to have the method, that's only ever called by a test. I'm feeling ambivalent
now, attracted because I know the code is tested and revulsed because the code
has no right to be where it is. I'm satisfying TDD and violating class
normalization.

What about separation of concerns between operation and verification? Is it
a horrible idea? Is it a wonderful idea?

A knee-jerk reaction is to draw a strict separation via mandate. Perhaps all
external system behavior needs to be strictly managed in the ATs and UTs and
all internal behavior (SUT responsibility) is in the actual SUT. We could
mandate that


I wonder where such a set of rules would lead us. It seems that TDD and DBC
both pointedly avoid such a separation in an attempt to make verification
mechanisms a first-class citizen of the systems under development (SUDs?).

Whatever the answer is, the question is: "In which ways should our tests affect
how our code is written?"

!commentForm
 Fri, 10 Feb 2006 18:28:51, JakeB[?],
I have also thought a bit about the problem that you are describing, with my current thinking being along these lines: an integral aspect of TDD is treating test code as a 1st class citizen; then by definition, the test alone justifies the existence of code that you say has "no right to be where it is".
 Sat, 11 Feb 2006 21:48:49, Paul Pagel, first class tickets
"No internal class contains a method whose only caller is a UT or AT fixture." This is problematic how you got here. The nature of test driven development is the tests are the mothers of the production code. They are the original and most important clients. If you are following YAGNI while designing and letting the tests guide you, then the behavior will show up in the system. While designing the system, often, the AT's and UT's are your only clients. I believe this seperation is not the problem.
 Mon, 13 Feb 2006 10:33:05, Tim Ottinger, I think those have to die.
There is hysteresis, of a sort. The way in is not the way out. You have to have test-only routines when you're starting, but they're only a step to somewhere else. Ultimately, if I write a test of function A, then I write function A, and never hook it into any other part of the system, I can delete both the test and the function. They're adding bulk without adding value. They're like lying comments. Why maintain something you don't need?

These are the most certainly deletable tests in the system. I'm looking for more principles that tell us what NOT to keep. I like what David Chelimsky is doing with this as well. I don't think that being a CodePackRat is a virtue.

Look at it this way, I write a test to call the "quack" method on an A/R account. Sure enough, true to TDD, when we call the "quack" method, it quacks. Great. The tests pass, we have more tests, more asserts, more protection against regression. There is one problem: the A/R account never needed to quack. If we delete the code for quack() method, then the tests fail -- but those tests don't need to exist. Now that's a little silly in an up-front kind of way, but the indication that it's wrong is that no production code ever calls quack().
 Tue, 14 Feb 2006 17:46:15, Paul Pagel, only if you want to cut out your liver
The AT's are there for this reason. To give the seperate modules(test-driven with their own UT's) a sense of purpose. If quack() is called in the production code, then their is some stacktrace of the AT's which should exercise its functionality as well. Also, if you are never getting there via code you are working on, how are you maintaining these ghost tests(tests/code which doesn't hook into the system. How do you get to code which isn't used?

However, if there is something I am looking over, and there exists code in the system which is never getting called, and no AT's fail, then go ahead and delete it. Just use source control.
 Thu, 16 Feb 2006 10:14:47, Tim Ottinger, You can cut anything you like.
You can write anything into a unit test. It doesn't have to be valuable or useful or even sensible. You can justify it by the UT and not even have an AT for it. How would anyone know? A development environment may help spot dead code, but having a UT means it isn't dead. You can have useless stuff lying about. You could not even know that it's useless.

I guess one of the hard things about TDD is that you only write UTs that you really need because of an AT that you really need. Knowing what not to write must be as hard as knowing what to write, and it's harder yet to know what to delete.

I guess I'm getting tired of all the TDD and Fitnesse articles spending all their time on the motivation for testing, and not enough on guidance for choosing what tests to write, which tests not to write, and what to delete.