You write a program to pass the test, extend the test or add further tests and then extend the functionality of the program to pass these tests.
The tests serve as the program specification so you have a detailed but abstract description of what the program should do.
As I started implementing a GUI, the tests got harder to write and I didn't think that the time spent on writing these tests was worthwhile.
I became less rigid in my approach, so that I didn't have automated tests for everything and sometimes implemented things before writing tests.
I'm giving up because I think it encourages conservatism in programming, it encourages you to make design decisions that can be tested rather than the right decisions for the program users, it makes you focus on detail rather than structure and it doesn't work very well for a major class of program problems - those caused by unexpected data.
The best design is one that's hard to test so you are more reluctant to take this approach because you know that you'll spend a lot more time designing and writing tests The most serious problem for me is that it encourages a focus on sorting out detail to pass tests rather than looking at the program as a whole.
I'll continue to test automatically wherever it makes sense to do so, but I won't spend ridiculous amounts of time writing tests when I can read the code and clearly understand what it does.