When I started unit testing I spent a great deal of time doing test after development. I started with test after because at the time I didn't know enough about the core testing concepts to drive out functionality test first. In hindsight I found that test after development was a great way to learn about the fundamentals of unit testing, mock objects and dependency inversion.
So as I started writing these unit tests, I found different situations that I just couldn't write a test for. And like anyone new to a subject they don't yet understand, I decided to ask a mentor for help. And this guidance has helped me grow as a software professional throughout the years. But I still had a few questions that just never got a direct answer. And it was these very questions that kept me up at night.
Possibly the biggest question I've tried to answer was related to unit testing private methods. In test after development you work to wrap a regression test around methods that you didn't write. Some of those methods are public so it's easy to create a new instance of the class and execute them. But others that are private or protected don't provide such easy access.
First I found a nasty reflection based approach that would allow me to keep the method private yet exercise it's behavior. This wasn't easy to maintain and often I found them of little value. Other times I would simply ignore the benefits of encapsulation and make the method public.
But since all these attempts left me feeling empty inside, I decided to chat with someone at work who had been writing code longer than I had been alive. He mentioned that if the method is public but it's not on the interface, it's effectively private. So if I'm truly coding to the interface and not the implementation, I shouldn't worry about these methods being public.
Although this made me feel better, it didn't answer the burning question about when private methods should be tested (or if they should be at all). This was something I found on my own when I started doing test first development. What I found is that private methods only came to be during the refactor step of test driven development. And since they were created during the 'clean code' step they were already tested. In fact if you found a private method in a class that wasn't tested you obviously weren't using it.
Over the last few months I've found that the value you get with regression tests by themselves isn't worth the time to write them in the first place. The real value is found through test driven development. You use unit testing to drive out the design of your software. In this way the software you are building is more loosely coupled making it much easier to change.
Although I still have a few questions surrounding test driven development that are not yet answered, I know that the muscle memory required to know when you should write a test and how to go about it comes from raw experience gained as you practice TDD. As the craft of software development matures I have a feeling that more and more shops will adopt these engineering practices to aid in the design process.