Unit tests == ugly code?


#1

I’ve found that when I write the tests first, and then write the code,
I’m not very concerned about what the code looks like. When the code
passes the test, I drink a beer and party, then move on to the next
test.

In practice, this means that I’m using a lot of ugly regex’s, poorly
named variables, and so on. I’d be more concerned about the
readability of the code if there wasn’t unit tests behind it. I’m
generally in a rush to finish whatever I’m doing, and figure that
since I have a bunch of tests, refactoring stuff later won’t be a big
deal.

Anyone else out there like me? Or should I be anal about writing good
code even with the tests? I guess that would be ideal, but I’d rather
get the functionality done first.

Joe


#2

On Wednesday, December 21, 2005 4:30 PM, Joe Van D.
mailto:removed_email_address@domain.invalid wrote:

Anyone else out there like me? Or should I be anal about writing good
code even with the tests? I guess that would be ideal, but I’d rather
get the functionality done first.

Joe

As soon as the code passes the test, you should look for opportunities
to
make your code better. Failing to do so is an option, but you should
recognize you are piling up a “technical debt” if you choose it. This
debt
ultimately will cause you grief, just as piling up debt on a credit card
without paying will eventually cause you financial grief.


#3

Joe Van D. wrote:

I’ve found that when I write the tests first, and then write the code,
I’m not very concerned about what the code looks like. When the code
passes the test, I drink a beer and party, then move on to the next
test.

In practice, this means that I’m using a lot of ugly regex’s, poorly
named variables, and so on. I’d be more concerned about the
readability of the code if there wasn’t unit tests behind it. I’m
generally in a rush to finish whatever I’m doing, and figure that
since I have a bunch of tests, refactoring stuff later won’t be a big
deal.

Anyone else out there like me? Or should I be anal about writing good
code even with the tests? I guess that would be ideal, but I’d rather
get the functionality done first.

This is the whole ‘design after’ or ‘refactoring’ paradigm:
make it work, then implement a proper design and prettify.
Passing unit tests prove that nothing was broken :slight_smile:

Joe

E


#4

I’ve found that when I write the tests first, and then write the code,
I’m not very concerned about what the code looks like. When the code
passes the test, I drink a beer and party, then move on to the next
test.

How many tests/day do ‘you’ pass? :wink:

In practice, this means that I’m using a lot of ugly regex’s, poorly
named variables, and so on. I’d be more concerned about the
readability of the code if there wasn’t unit tests behind it. I’m
generally in a rush to finish whatever I’m doing, and figure that
since I have a bunch of tests, refactoring stuff later won’t be a big
deal.

Anyone else out there like me?

Pretty much the opposite. When I do TDD, I am very careful about the
code I write. I work hard that my tests look good (so that I can see
what I meant when writing it) and robust. And I program so I can test
(less monolithic etc.). I should do much more TDD.

Patrick


#5

That’s interesting.

On of the TDD pitches is that the tests present a constant design
pressure
on the code encouraging refactoring as you go, the theory being bad code
isn’t so testable.

My experience is limited, but I find this mostly true, and it helps me
name
things since I’m writing code to a much clearer context then if I’m just
coding “in the wild” so to speak.

e.g.

def test_list_archived_articles
a=Article.find_by_status “old”

test here

end

My test to check if my list articles works shows some strange semantics,
and
I rewrite as:

def test_list_archived_articles
articles = Article.get_archived

test here

end

and I update Article to encapsulate how archiving is implemented.

If you are writing tests and not refactoring, I think you are missing a
main
point of TDD- design rather then QA.

Also, without the refactoring, your tests would likely become stranger
as
your project gets bigger, getting to the point where you can’t figure
out
how to effectively test new features.

At least that’s the theory.

Regards,
Nick


#6

Joe Van D. wrote:

I’ve found that when I write the tests first, and then write the code,
I’m not very concerned about what the code looks like. When the code
passes the test, I drink a beer and party, then move on to the next
test.

Anyone else out there like me? Or should I be anal about writing good
code even with the tests? I guess that would be ideal, but I’d rather
get the functionality done first.

Actually, my biggest problem for a long time was ugly tests (mostly
from a desire to mock everything, and never to inject), but I’m
getting better at that. No, you’re going to have to stop, look at your
code, and say, “Is this readable? If not, how can I make it readable?”
Having passing tests will give you more freedom to do so, hopefully.

Devin


#7

Joe Van D. wrote:

deal.

Anyone else out there like me? Or should I be anal about writing good
code even with the tests? I guess that would be ideal, but I’d rather
get the functionality done first.

Joe

You have to remember that TDD was popularized by eXtreme Programming,
where it is combined with several other practices. There are few that
really help. First, continuous integration ensures that all your tests
are run frequently. Collective code ownership ensures that others on the
team get to smell your funky code (And give you a hard time about it.)
But, there are two that are really key: Merciless refactoring means that
any time there is an opportunity to improve your code you take it. And,
pair programming means that there is another person sitting next to you
who is able to slap you silly when you code badly. You can do TDD
without these other practices, but I’d advise that doing it without at
least doing merciless refactoring and continuous integration is a little
silly (But better than nothing.) Finally, if your code sucks you have no
one to blame but yourself, and it’s certainly not TDD’s fault :-p


#8

On Wednesday 21 December 2005 07:20 pm, Eero S. wrote:

figure that since I have a bunch of tests, refactoring stuff
later won’t be a big deal.

Anyone else out there like me? Or should I be anal about
writing good code even with the tests? I guess that would be
ideal, but I’d rather get the functionality done first.

This is the whole ‘design after’ or ‘refactoring’ paradigm:
make it work, then implement a proper design and prettify.
Passing unit tests prove that nothing was broken :slight_smile:

I cannot in a million years imagine coding without design. I’ve
never coded tests first (I test each class after coding it), but I
can’t imagine why writing the tests first would make one not
design. If it did make me not design, I wouldn’t code test first –
I’d make test jigs after.

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid


#9

Steve L. wrote:

I cannot in a million years imagine coding without design. I’ve
never coded tests first (I test each class after coding it), but I
can’t imagine why writing the tests first would make one not
design. If it did make me not design, I wouldn’t code test first –
I’d make test jigs after.

I tend to sketch first, doodling out the initial pass at an app, trying
out stuff to test the waters and see if something that popped into my
head is [not as hard|as hard|much harder] than I thought it might be.

A lot of what I do is driven by a “Hmm, I wonder what this button does
…” mentality, and test-first can interfere with the interesting
accidents and failures.

But as apps grow, they can get gnarly, and unless the app is a toss-off
(though how can you tell?) I’ll then go and rewrite it, but this time
using unit tests to avoid the nasty bits. And by that point I likely
have some general design to guide me.

James

http://www.ruby-doc.org - Ruby Help & Documentation
http://www.artima.com/rubycs/ - Ruby Code & Style: Writers wanted
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys
http://www.30secondrule.com - Building Better Tools


#10

Joe Van D. wrote:

I’ve found that when I write the tests first, and then write the code,
I’m not very concerned about what the code looks like. When the code
passes the test, I drink a beer and party, then move on to the next
test.

You’ve got the order right, you’ve just forgotten
the third step, and most important step to ensure
agility: refactor. The rhythm is Red-Green-Refactor.

Regards,


#11

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2005.12.22 14:06, Steve L. removed_email_address@domain.invalid wrote:

it. I’m generally in a rush to finish whatever I’m doing, and

I cannot in a million years imagine coding without design. I’ve
never coded tests first (I test each class after coding it), but I
can’t imagine why writing the tests first would make one not
design. If it did make me not design, I wouldn’t code test first –
I’d make test jigs after.

Heh, of course you need to have some idea of what you are
doing (and, in fact, the better you design intuitively, the
easier the refactoring). If you are coding strictly by the
“write a test…implement the method…write another test…”
method, you are likely to end up with slightly less elegant
code, occasionally with repetition and all-in-all less-than
ideal organization. Refactoring is the phase of fixing this,
shuffling functionality around, extracting common code etc.

SteveT

E
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDqlnsxvA1l6h+MUMRApzAAJ9S9+REQ4qvVCvWA9d5RJrpIsFtAwCfR3AO
VCrLbVeshFlcBgmU9c30mzw=
=bCPh
-----END PGP SIGNATURE-----


#12

On 12/21/05, Steve L. removed_email_address@domain.invalid wrote:

it. I’m generally in a rush to finish whatever I’m doing, and

I cannot in a million years imagine coding without design. I’ve
never coded tests first (I test each class after coding it), but I
can’t imagine why writing the tests first would make one not
design. If it did make me not design, I wouldn’t code test first –
I’d make test jigs after.

Oh, I spend a lot of time on class designs (and how the various
objects interact with each other). I tend to follow the ‘tracer
bullet’ philosphy outline in the pragprog books.

It’s just that, within the beautifully designed functions and classes,
lies unspeakable monsters. (ok, maybe not that bad)


#13

On 12/22/05, Steve L. removed_email_address@domain.invalid wrote:

I cannot in a million years imagine coding without design.

Neither can I – which is precisely why I never write my classes
before my tests. Writing a class is not design; that’s called
“programming by intention”. Figuring out what you need a class to do,
and then specifying the API is design. This is (part of) what the
tests do. They give you a chance to work with the interface as a
client of that interface to see how things fit together before you
commit yourself to the implimentaiton.

I’ve
never coded tests first (I test each class after coding it), but I
can’t imagine why writing the tests first would make one not
design. If it did make me not design, I wouldn’t code test first –
I’d make test jigs after.


Regards,
John W.
http://johnwilger.com


#14

On Friday 23 December 2005 10:13 am, John W. wrote:

On 12/22/05, Steve L. removed_email_address@domain.invalid wrote:

I cannot in a million years imagine coding without design.

Neither can I – which is precisely why I never write my classes
before my tests. Writing a class is not design; that’s called
“programming by intention”. Figuring out what you need a class to
do, and then specifying the API is design. This is (part of) what
the tests do. They give you a chance to work with the interface
as a client of that interface to see how things fit together
before you commit yourself to the implimentaiton.

Hi John,

How does coding your tests first affect your enjoyment of coding?

If you find out later that your (interface, not implementation)
design for a class wasn’t exactly right, do you then recode your
tests first and then recode your class?

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid