How valuable a particular approach to testing is depends on how mission critical the system under development is, and how much some other mission critical system depends on it. A simple guestbook script for your website could hardly be considered mission critical, but if the website it runs on could potentially be compromised by a bug that allowed unfiltered input to the database and that site offers some vital service, then it suddenly becomes a lot more important for the guestbook script to be thoroughly tested. The same is also true of framework/library code. If you develop a framework with a bug, then every application that uses that framework feature also has that same bug.
Test driven development gives you an extra layer of safety when it comes to tests. If you write the tests alongside or even after the code you want to test, then there's a real risk that you get the tests wrong. If you write all the tests first, then how the code works internally can't influence what you write tests for, and therefore there's less possibility that you inadvertently write tests that think that a particular erroneous output is correct.
Test driven development also encourages your developers to write code that's easy to test, because they don't want to give themselves even more work to do! Code that's easy to test tends to be code that's easy to understand, reuse and maintain.
And maintenance is where you will really reap the rewards of TDD. The vast majority of the programming effort expended on software is maintenance related. This means making changes to live code to give it new features, fix bugs or adapt it to new situations. When making such changes, you want to be sure that the changes you make have the desired effect, and more importantly, they have no unexpected knock on effects. If you have a full test suite for your code, then it's easy to verify that any changes you make are not breaking something else, and if the changes you make do break something else then you can quickly locate the reason why. The benefits are long term.
You said the following in your question:
I see some benefit to writing tests for some things, but very few. And
while I like the idea of writing the test first, I find I spend
substantially more time trying to debug my tests to get them to say
what I really mean than I do debugging actual code. This is probably
because the test code is often substantially more complicated than the
code it tests. I hope this is just inexperience with the available
tools (rspec in this case).
This seems to suggest to me that you're not quite getting testing. A unit test is supposed to be extremely simple, just a sequence of method calls, followed by an assertion to compare the expected result against the actual result. They're meant to be simple because bugs in your tests would be disastrous, and if you introduce loops, branching or other program throw control into the test then it becomes more likely that the test will have a bug introduced into it. If you're spending a lot of time debugging tests then it indicates that your tests are overly-complicated and you should simplify them.
If the tests can't be simplified, than that fact alone suggests that there's something wrong with the code under test. For example if your class has long methods, methods with a lot of if/elseif/else or switch statements or a high number of methods that have complex interactions dictated by the current state of the class then tests will by necessity have to be extremely complex to provide full code coverage and test all eventualities. If your class has hard coded dependencies on other classes then this again will increase the number of hoops you will have to jump to in order to effectively test your code.
If you keep your classes small and highly focused, with short methods with few execution paths and try to eliminate internal state then the tests can be simplified. And this is kind of the crux of the matter. Good code is inherently easy to test. If the code isn't easy to test then there's probably something wrong with it.
Writing unit tests is something that benefits you in the long run, and avoiding them is simply storing up trouble for later. You might not be familiar with the concept of technical debt, but it works a lot like financial debt. Not writing tests, not commenting code, writing in hard coded dependencies and so in are ways of going into debt. You "borrow" time by cutting corners early on and this might help you hit a tight deadline, but the time you save earlier on in the project is on loan. Each day that goes by without cleaning up the code, commenting it properly or building a test suite will cost you interest. The longer it goes on, the more interest accumulates. Eventually, you'll discover your code has become a tangled mess that you can't make changes to without triggering unintended consequences. The interest on the time loan you took out early in the project and failed to pay back later has come back to bite you and now you're effectively bankrupt - The time taken to fix the problems with the existing system exceeds the time it would take to rewrite it from scratch.
You could think of writing unit tests early and keeping them up to date as a form of "technical credit". You're putting time in the bank by spending it early on in the project on following good practice. You'll earn interest on this foresight later on when you get to the maintenance phase of the project. When you want to make a change, you can easily validate the correctness of the change and that it doesn't have any unwanted side effects, and you can get updates out the door quickly and without fuss. If bugs turn up, you can add a new unit test that exercises the bug, then fix the bug in the code. When you next run the unit test you'll be able to verify that the bug was fixed, and that it didn't cause any other problems. Further more, you'll avoid "regressions", where a previously fixed bug is reintroduced because there's nothing documenting why things have been changed.
TL:DR - Yes, they are a real world help, but they're an investment. The benefits only become apparent later.