Unit Testing for Developers and Managers
Tuesday, September 30th, 2008.
“We need to rewrite the system.”
Thus begins the story of yet another developer trying to convince their manager to adopt test-driven development (or any other methodology or technology). There’s a good chance this developer’s been reading all sorts of stuff on blogs (like those linked here) that have convinced him that salvation lies that way.
Don’t get me wrong.
There’s a good chance the developer’s right.
It’s just that that’s besides the point.
Developers and Managers
There’s a difference between how developers view a practice and how a manager (defined for the purposes of this post as someone in charge of delivering something) view that same practice. From a developer perspective, Ian’s point about unit testing is spot on:
“The problem is that the most important step is not doing it right, but doing it at all.”
Yet, as Ian himself points out in the title, this is a learning issue. If you want to learn to swim, there’s no replacement for jumping in the pool.
The manager’s perspective is a bit different.
Yes, we want our developers to improve their skill set. Yes, we understand that unit testing will ultimately improve quality. Yes, we know developers need to practice these skills as a part of their job. But, and it’s a big ole’ but, when it comes time to sink or swim, and we’ve got a deadline, those desires need to be balanced with delivering. Accounts of unit testing adoption efforts resulting in more (test) code to support with little apparent improvement in quality in the short term, well, they scare us. Arnon’s post gives more links supporting that feeling.
What’s a Unit Test anyway?
Is it any class that happens to have a TestFixture attribute on it?
If we are to “decouple” unit testing from good design, as Roy has described, that’s a not-improbable outcome. If the design of the system is such as there aren’t any real “units”, what exactly are we testing? Regardless of static or dynamic typing, replaceability of code, and other technological things, does the fact that all TestMethods in that TestFixture complete successfully mean anything? In other words, what did the test test?
It is clear that these tests cost something.
It’s more code to write. It’s more code to maintain.
The question is, what value are we getting from these “unit tests that any developer without design skills can write”?
The manager in me doesn’t like this return on investment.
By the way, TDD is as much the evolution of unit testing as the screw driver is the evolution of the hammer. But that’ll have to wait for a different post.
What’s Design Got To Do With It?
If you’re looking for the technical ability to write a test fixture and replace calls to other classes, then design has nothing to it.
If tests are to be valuable - design has everything to do with it.
The difficulty our developer is having unit-testing the system is a symptom of design problems. There’s a good chance that’s why he suggested a rewrite.
By the way, please do a search & replace in your vocabulary on the word “rewrite” with the word “redesign”. The code’s syntax isn’t the problem - it’s not the “m_”, camel case, or anything like that. It’s not that if the code was rewritten under the same design that all problems will go away.
Redesign, or do nothing.
The community’s been discussing the issues of coupling, interfaces, mocking, and tools at length in the context of testability. I won’t reiterate the debate here but I’ll tell you this:
If logic is duplicated, if the code is tightly coupled, if there is no separation of concerns, the unit tests will be useless - even if they “test” the class in isolation.
Cut the coverage crap
Metrics lie.
The fact that there’s a bunch of other code which calls 100% of the system’s code and doesn’t contain false assertions doesn’t mean that the code is high quality or doesn’t contain bugs.
In a well designed system, most “logic” will be contained in two “layers” - the controllers and the domain model. These classes should be independent of any and all technological concerns. You can and should get high unit test coverage on classes in these layers. Shoot for 100%, it’s worth it.
Testing domain models is all about asserting state. While using setters to get the domain objects into a necessary initial state is OK, setters should not be used beyond that. Testing controllers is primarily about interactions - mocks will probably be needed for views and service agents. Commands do not need to be mocked out.
Most other layers have some dependence on technology that makes unit tests relatively less valuable. Coverage on these layers is most meaningless. My guidance is to take the effort that would have been spent on unit testing these other layers and invest it all in automated integration tests. You’re likely to get a much higher return on investment. Much higher.
Much.
Everybody’s Right
Developers aren’t just born knowing good design, testing, or anything else. Universities, colleges, and most vendors do little to change that state of affairs. Books help, a bit, but when learning to swim, you’ve got to get your feet wet, and on the job training is, by and large, all there is. As such, lowering the barrier to entry is important.
Keeping in mind the Dreyfus model of knowledge acquisition, it’s not about “dumbing down” software development, it’s about bringing novices up to speed:
“In the beginning [novices] learn to recognize objective facts and features, relevant to the skill. Characteristic of relevant elements are that they can be recognized context-free, i.e. without reference to the overall situation. The novice acquire basic rules to follow, acting upon those facts and features. The rules are also context-free, i.e. no notice is taken to the surroundings. On account of this the novice feels very little responsibility for the result.” (emphasis mine)
Managers are ultimately responsible for the result.
Managers shouldn’t necessarily sacrifice their projects on this altar of learning. Organizations need to find ways for developers to safely practice these techniques as a part of developing their “human resources”. First of all, this needs to be communicated to everyone - that the organization understands the importance of these techniques, the desires of developers to adopt them, and the projects that need to be delivered.
Some projects may be allocated additional non-functional requirements: the software will be developed test-first, there will be at least 80% unit test coverage, etc. It can make sense to have developers spend some time on these projects after finishing one more delivery focused project and before going onto another one. As more developers become proficient with unit testing and design, the delivery focused projects can start to benefit from these skills.
It’s a gradual process.
The Important Bit
No matter how you go about unit testing, do periodic test reviews.
Just like code reviews.
That’s it.
Related Posts
|
If you liked this article, you might also like articles in these categories:
If you've got a minute, you might enjoy taking a look at some of my best articles.I've gone through the hundreds of articles I've written over the past 4 years and put together a list of the best ones as ranked by my 2000+ readers. You won't be disappointed. If you'd like to get new articles sent to you when they're published, it's easy and free.Subscribe right here. Something on your mind? Got a question? I'd be thrilled to hear it. Leave a comment below or email me, whatever works for you. 8 CommentsYour comment... |







September 30th, 2008 at 4:14 pm
Great post Udi, I have been thinking a lot lately about the value of unit tests in certain parts of a system, and I think you hit the nail on the head.
October 1st, 2008 at 12:43 am
An excellent post. I think, and hope, what you are saying is any code that does not add *business* value is of low value, and tests that have no clear purpose, or that further concrete an already weak design, will ultimately decrease business value.
Saying “we have tests” is relatively worthless, saying we have our core logic fully tested and can now refactor or evolve safely has immense value.
October 1st, 2008 at 3:09 am
[…] Unit tests are not technically hard, as Udi points out, what is a test? Anything with TestFixture on it? […]
October 1st, 2008 at 9:05 am
Casey,
I think that that’s about right.
October 1st, 2008 at 9:43 am
Alleluia.
October 1st, 2008 at 2:54 pm
Excellent post, I will go “broadcast” in my blog.
Some managers sacriface yours project only by cost and pmi pratices, but to test domain model is very important. Managers should not to do this.
October 10th, 2008 at 2:30 am
[…] original post about increasing TDD adoption. Roy updates some of the reaction here and here. Udi comments on my reaction that the most important thing is to being writing tests and then learn how to write […]
October 11th, 2008 at 2:28 am
[…] as Udi Dahan points out, we often feel we are not at liberty to go off experimenting with change at the expense […]