Joel's question was something like this. Suppose you wanted to set a bit somewhere that caused a low resolution image to be displayed rather than a high resolution image. How would you use TDD to get that to work? Would you write a test that scraped the screen to show that the image was in low res?
Of course not. You already know that the JPEG library works. You already know that if you call it with the right arguments it will display in low resolution. What you need to test is that the bit you set gets translated into the appropriate calls to the JPEG library. So you mock out the JPEG library with a very simple module controlled by your test. Then you set the bit, and request display. The Mocked JPEG library will remember how it was called, and then the test can check to be sure that it was called correctly.
OK, so how would you test the internals of the JPEG library? I don't know a lot about JPEG rendering, but I presume it's about compression, decompression and bitmaps. Compression and decompression are just algorithms. Algorithms have predictable outputs from given inputs. So you set up a series of very simple inputs and make sure you get the predictable outputs. You set up the inputs so that the internals of the JPEG algorithms are covered. The same logic holds for the bitmaps. You don't have to render them on the screen. Simple little bitmaps can be rendered into memory buffers that the tests can examine. By simple, I mean SIMPLE. 3X3, 5X5, 8X8. Simple. Again, you structure your input data to cover the bulk of the code.
None of this is rocket science. None if it is perfect. But a suite of 50 tests that demonstrates that 90% of your logic is correct can make a huge difference when you want to make changes.
Can you ever completely eliminate manual testing? Of course not. But you can significantly mitigate it. You can reduce manual testing to a few very strategic tests rather than thousands of painfully tedious test plans.