I'm dealing with a lot of that cultural resistance in my
current gig. I don't do TDD well enough myself yet to
really drive the process. When I was at Progressive, the
mandate that you had to work with the Thoughtworks guys
to learn to do it the right way was a very good policy.
Unit tests only work well if the developer writing them
has a good understanding of object oriented design and
the concept of inversion of control. From what I can see
most .net developers don't and I believe that's why it
hasn't picked up as much in that community as it has
others. It's very hard to test some static method on a
class that reads its configuration from some predefined
location, talks to some hard coded database that has to
be available, and calls some web service before
returning. I'd give up on that pretty quickly too. As
long as a class sticks to a single responsibility and
isn't responsible for constructing it's collaborators
then creating and maintaining tests is a breeze and
perhaps even enjoyable.
We normally hear 'Why are we writing this twice? The
client won’t pay for double the work! I describe it as
similar to double entry book-keeping. It looks like
double the work but it is just verifying that everything
balances. i.e. I expect some code it to do this: +1
(setup), and I verify is has: -1 (assert). When
everything balances we have a stable system. If we don’t
we just have to ‘hope’ that it all works.
One obstacle I have noticed personally is that it is
difficult to know as a beginner what exactly to test. I
have seen (and also written) tests that were almost
trivial, to tests that were way too complex.
I think one of the major benefits to unit testing is
that it can lead to much deeper understanding of the
code. As an example, I was recently working on involved
subclassing a quirky class in Ruby. Using tests I was
able to clearly spell out exactly what I was expecting
to happen, and see where it was messing up. Then,
instead of blindly doing search and replace type
changes, I only changed as much as necessary to get the
tests to pass. This showed some subtle differences in
some parts of the code, as some things that looked
similar required different changes.
Before I wrote out the tests, I tried some blind
changes, which totally did not work. So in this case its
not a case of faster development, but something working
where it didn't work before.