The first time I encountered software testing was at university in my 2nd year. We had previously learnt how to write procedural software in Pascal and C, and had started to learn about different software paradigms such as object oriented programming (using C++). One of the lectures talked about how we could add assert statements to our code to test that the program was acting sensibly when we were developing it (we would of course turn off the asserts in ‘production’), and introduced the idea of pre- and post-conditions for methods (pre-conditions define what our function expects to be true when it is invokes, and post-conditions define what the consumer can expect to be true from the result). Of course back then I didn’t think testing was interesting or cool, so I didn’t really pay it much attention. Even when I did add assertions in my code, these were not automated and so were rarely run, and so had little visibility, and failed to keep me interested.
A year later I was preparing for my first summer internship where I would be writing Java code in an environment that encouraged the use of Test Driven Development. This was not a concept that I had really come across before, but after going through some tutorials on using JUnit and how to write code in a test driven approach, I fell in love with test automation. Suddenly I started writing lots of tests for my code, but my approach was unfocused and I ended up just adding tests left, right, and center; the result of this was lots of tests which had little value (most of which were written after the implementation code). But hey, at least I had lots of tests … right?
Around the time I started applying for ThoughtWorks, I started to take the test first approach more seriously. Now my testing felt a lot more focused, and by the end I had a full regression suite which accurately described the way I expected my programs to work. I had heard about the different layers of the test pyramid, but only really starting writing these different types of tests when at ThoughtWorks University. The way I approached testing felt a lot more refined, and I felt better about the code that I wrote.
Over the past year as a graduate developer consultant, I continued to use TDD (And got burnt when I didn’t follow proper testing practice) and felt good about it, but still did not feel completely satisfied. When it came to my year review, I said that one of my goals was to try and change my perspective on proper software testing, but I felt that I had not really achieved that. Soon after, the whole TTD is dead thing happened, and everyone was talking about testing. For me this was great, because I gained so much insight into testing in our industry from both internal and external discussions about best practice. Watching the Is TDD Dead video stream (Featuring DHH, Kent Beck, and Martin Fowler) really helped bring everything together in my mind and I finally understood: Testing is about confidence.
Of course I really knew this all along, but I think it took a long time for this concept to take hold. How much is enough testing? How much is too much testing? Well, it depends … what level of confidence would writing this test give you? Writing a test for a trivially simple method probably wont give you much confidence (and will probably be a bump in the road when refactoring later), but writing tests around more complicated business logic, or integration points will give you more confidence. You might have functional tests that at first gave you a lot of confidence, but these became flakey and now every every time they fail in a non deterministic way, your confidence in them takes a dive. 
The value of your tests depend on the confidence they give you.
If a tests gives you no confidence, it has no real value.