News for hackers. Stuff that matters.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by nostrademons on Wednesday February 04, 2009 @02:44AM (#465407)
In this case, I think Kent's right. Joel's doing it wrong.

You should never have 10% of your unit tests depend upon the location of a menu. You should have one unit test that depends upon the location of the menu, and everything else should be isolated by stubs, shunts, mocks, whatever. Otherwise, they aren't really unit tests, because they're testing more than a unit.

I didn't realize how wrong I was doing it until I got to Google. (Then again, a lot of Google's best programmers are doing it wrong too.) Perhaps this is because doing the right thing - mocking out your dependencies and testing only one feature per test - is often harder in the short term than just running all your code when you test the topmost layer. But I think the point needs to be hammered home: most programmers who're doing "unit" testing are not doing unit testing, and their code would be much less brittle if they took the time to stub out lower layers.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by axod on Wednesday February 04, 2009 @05:01AM (#465522)
I agree, in theory. However, when you're quickly iterating, redesigning, changing how things work, having to completely rework the unit tests as well is pretty much wasted effort.

I think it depends on the project - is it a 'design up front, go away code once' project, or an iterative constantly changing thing.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by swombat on Wednesday February 04, 2009 @05:09AM (#465531)
'Fraid not, axod. It's when you're quickly iterating and changing lots of stuff that quality unit testing helps you the most. Let's look at 2 possible scenarios:

1) You don't bother testing much. You make lots of changes, iterate quickly. Before the changes, you have code that, let's say, you know works. After the changes, you know there's probably bugs, but you don't know where.

2) You test fairly thoroughly. You make lots of changes, iterate quickly. Before the changes you have code that you know works. After the changes, you know where most of the bugs are because your tests tell you where they are.

It's the difference between walking with your eyes open or closed... it may be more work to process all that information about obstacles, but it sure is helpful if you want to avoid those obstacles.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by trapper on Wednesday February 04, 2009 @07:38AM (#465658)
There are two schools of thought in programming I have seen.

1. Design it right the first time, tests and all.

2. Build a throwaway, no tests, little refactoring as you quickly iterate

Programmers who fall into category 1 in my experience mistakenly believe that they understand the requirements of the software they are writing. Category 2 programmers tend to be ones who actually deal with users/real world, and know that they don't understand the requirements.

My position is that if you are building something for the first time, you are going to get it wrong, so get it wrong as quickly and cheaply as possible. This means getting it in front of users as quickly as possible, bugs and all.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by swombat on Wednesday February 04, 2009 @09:39AM (#465779)
You're assuming that you'll get something in front of users more quickly without writing tests. I find that's not the case in my experience.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by nostrademons on Wednesday February 04, 2009 @01:06PM (#466160)
I find there's a balance to be struck. You want to get stuff in front of users quickly, but if that stuff sucks so much that it's unusable, you aren't going to release it (and if you did, nobody would use it). So you want enough tests that you can be reasonably confident of the code and not spend a lot of time debugging, since debugging is the real timesink that'll kill you.

I often find that I unit test all but the latest layer. As soon as I start depending on code from something else, it's time to write some tests. But if I just wrote something, it's probably in flux and tests would just prematurely lock down the interface. Write the code, write the client (which probably requires that you rewrite the code), and then write the tests in lieu of debugging the code.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by trapper on Wednesday February 04, 2009 @07:27PM (#466824)
Also, to get something in front of users, you rarely need to be doing anything remotely complex. It's not like writing a disk based inverted index or a filesystem. When writing tools like those, obviously testing is important.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by trapper on Wednesday February 04, 2009 @06:04PM (#466697)
I'd love to see some research on this. I would hypothesize that there is a point of problem complexity where the lack of tests becomes a negative for productivity.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by mrandle on Thursday February 05, 2009 @11:39AM (#468160)
I second this suggestion (and agree with the hypothesis, although its probably not just a function of raw problem complexity, other variables must come into play)

Hasnt it been done already? Couldnt find anything I would class as 'scientific' with a quick google search. Would be a good thesis for someone.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by axod on Wednesday February 04, 2009 @06:12AM (#465585)
I disagree.

If I'm constantly changing my mind about how best to do something, I don't want the massive overhead of having to change unit tests all the time as well.

I'll test as I go, in the code.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by Retric on Wednesday February 04, 2009 @11:42AM (#465965)
If your testing in the code then your doing unit tests. But probably in a poor fashion.

Unit tests should hook into the application in such a way that you can reorder the GUI and change nothing.

If you are using Unit tests correctly then any change to the code base at worst requires 10% of that effort to change the test cases. If you can think of any meaningful change that is worse then that your something is wrong with how you're testing.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by gdee on Wednesday February 04, 2009 @11:23AM (#465917)
"If I'm constantly changing my mind about how best to do something" then you're finding /more/ not /best/ ways.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by davidw on Wednesday February 04, 2009 @07:20AM (#465644)
> Before the changes you have code that you know works. After the changes, you know where most of the bugs are because your tests tell you where they are.

The tests tell you where the tests fail. Some of those failures may be due to bugs, and others may simply due to the way your code now works.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by fizx on Wednesday February 04, 2009 @05:29AM (#465553)
I'll chime in from recent experience. I had to pull a dependency in my project because it was causing heisenbugs that I couldn't root out. Without tests, I wouldn't have known. With tests, it took 2 hours to replace (diff -200 +250), and I'm confident the library still works. Without tests, it would have taken several more, at least.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by mattm on Wednesday February 04, 2009 @07:29PM (#466827)
How long did it take to write the tests?
Re:"Joel Spolksy is wrong about my work" - Kent Beck by fizx on Thursday February 05, 2009 @12:02PM (#468219)
I write tests as I develop, and they take the place of going to the browser or a repl and poking around at my work. In some sense, testing takes zero or negative net time. It would be hard to measure gross time, because it occurs in such small increments.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by DougBTX on Wednesday February 04, 2009 @08:56AM (#465714)
> After the changes, you know there's probably bugs, but you don't know where.

Which highlights one of the "problems" with unit tests: if something fails, you have to take time to go and fix it. If you have no tests, you can assume there are no bugs because you are such a great programmer, then go home after a job well done.

That there actually are bugs there doesn't bother you, because you don't know about them. It takes less time to write buggy code.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by axod on Wednesday February 04, 2009 @09:06AM (#465728)
The alternative, is to build you code in a way which tells you quickly about bugs... decent logging, etc
Re:"Joel Spolksy is wrong about my work" - Kent Beck by swombat on Wednesday February 04, 2009 @09:37AM (#465773)
I do think he was being sarcastic.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by axod on Wednesday February 04, 2009 @09:15AM (#465743)
>> "Before the changes you have code that you know works. After the changes, you know where most of the bugs are because your tests tell you where they are."

No. More often than not, if you change was a large architectural one, which is often the case in young software, your tests are now irrelevant, or broken.

>> "It's the difference between walking with your eyes open or closed... it may be more work to process all that information about obstacles, but it sure is helpful if you want to avoid those obstacles."

Do you seriously think people are just blindly coding and never testing anything here?

  while(true) {
    writeABitOfCode();
    while (!compile()) fixCompilationErrors();
    testThingsYouMightHaveChanged();
    checkLogsForIssues();
  }
Re:"Joel Spolksy is wrong about my work" - Kent Beck by swombat on Wednesday February 04, 2009 @09:42AM (#465784)
* testThingsYouMightHaveChanged();*

If you change that into writeAnAutomatedTestForItAndRunYourTestSuite() you get the following benefits:

1) Every test you write accrues value onto your test suite and helps you avoid problems later;

2) You don't need to spend time to figure out what you might have broken with your change - your test suite tells you in seconds;

3) You can say with some measure of certainty that it's extremely unlikely that your change broke anything.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by axod on Wednesday February 04, 2009 @11:30AM (#465939)
BUT you then have to modify:

  while (!compile()) {
    fixCompilationErrors();
    fixUnitTests();
    rewriteUnitTestsThatNoLongerMakeSense();
    WriteNewUnitTests();
  }
Your iterate loop just became maybe twice or 3 times as long. Less iterations = worse code.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by Retric on Wednesday February 04, 2009 @11:51AM (#465987)
rewriteUnitTestsThatNoLongerMakeSense

Delete em. You should be iterating your unit tests.

Over time you will find some really useful unit tests for common mistakes, and others that are basically useless. Try and approach things from the perspective of what you would like to know works and not just tossing everything and the kitchen sink at the problem. When you find a bug add a unit test just in case it comes back, if you change major parts of the system, port the most useful unit tests and delete the rest.

I think of unit tests as saving you from the (I thought I just fixed this) problem.

PS: The major advantage of this approach is you keep adding more tests to the older parts of the system, which are also the most costly to change because other parts of the system assume it works. And assumptions you and your code is making can be really hard bugs to find and fix.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by nostrademons on Wednesday February 04, 2009 @01:09PM (#466166)
I think the best benefit of unit tests is really saving you from the "Will this break anything?" problem. Uncertainty is the real big killer for programming productivity; if you know what to code, you just type it out and you can get like 10 lines/minute. So have some way that you can run things and say "I know this broke something" or "I know this didn't break anything."
Re:"Joel Spolksy is wrong about my work" - Kent Beck by DougBTX on Wednesday February 04, 2009 @01:38PM (#466223)
testThingsYouMightHaveChanged requires running your tests manually, which is slow and hard to fully reproduce later. It also depends on being able to make strong predictions about what your change affects, unit testing assumes that anything could have broken.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by shiro on Wednesday February 04, 2009 @07:08AM (#465638)
> I think it depends on the project - is it a 'design up front, go away code once' project, or an iterative constantly changing thing.

I think your line is too coarse. I do heavily rely on unit tests even in "iterative constant changing projects". But in the very early "sketching" stage of development I don't bother to write tests. I just play with code on REPL (I work with Common Lisp or Scheme most of the time), in a flat namespace. Then, once I start putting code snippets together into packages (CL) or modules (Scheme), that's about the time I start writing tests as well. After that, even I constantly change stuff, sometimes drastically, unit tests do help me a lot.

It is true that you need effort on reworking on the tests. Actually I think writing tests needs more work than writing actual code. And I think that's the right thing. Writing something that works is an easy part. Making sure it doesn't break in every possible situation is much harder. In language like CL, you can fairly quickly write something that takes typical input and reasonable output without serious thinking. To make sure it works in every corner case you have to think much harder and precisely, and test code reflects that thinking.

(NB: I know some programmers who seem to think out those corner cases in their brain and just spit out a beautiful code at the first attempt. They may not need support from test code, I guess.)

Re:"Joel Spolksy is wrong about my work" - Kent Beck by zaius on Wednesday February 04, 2009 @04:14AM (#465483)
As someone who is relatively new to the world of testing, I think I finally understand the point of stubs/mocks/etc. Thanks!
Re:"Joel Spolksy is wrong about my work" - Kent Beck by jsdalton on Wednesday February 04, 2009 @08:27AM (#465692)
Do you know of any good texts or articles that describe the "right" way to test?

I put myself in the category of mediocre test writer, because I do bump into the problem fairly regularly of having a lot of tests fail when I do a rewrite. I'd love to learn how to write better tests...and your last paragraph seems to scratch the surface of a superior approach.

Re:"Joel Spolksy is wrong about my work" - Kent Beck by anthonyrubin on Wednesday February 04, 2009 @10:13AM (#465823)
The Google Testing Blog can be helpful:

http://googletesting.blogspot.com/

Re:"Joel Spolksy is wrong about my work" - Kent Beck by nostrademons on Wednesday February 04, 2009 @01:16PM (#466182)
Seconding this. I think the internal Google training materials were some of the best I've run across, and the Google Testing Blog is basically the public face of those.
Re:"Joel Spolksy is wrong about my work" - Kent Beck by mhb on Wednesday February 04, 2009 @09:19AM (#465752)
Dive Into Python has a couple of good chapters on unit testing. Maybe you're looking for something more advanced though. If so, I think he gives some references for further reading.

http://diveintopython.org/unit_testing/index.html