Testing! Getting better at testing will make you seem like a better programmer even if your coding style doesn’t change at all. No matter how beautiful and clear your code is, if it’s full of bugs it’s not good code.
It’s kind of ironic that I’m writing a post about testing because honestly I’m not very good at it. Better than I used to be, especially since I started working at a company that actually has unit tests and insists they all pass before you push anything to production, but testing is still not one of my strengths. You don’t have to be amazing for it to be worth doing more testing, though. Some improvement is always better than none.
The thing most programmers, including me, seem to struggle with the most is not being able to think of anything but the happy path through our code. It’s like how when you’re trying to proofread your own writing you see what you meant, not what’s actually there in terms of typos and missing or repeated words. We test the way we meant our code to work instead of thinking of how it could break, and then we decide testing our own code is a waste of time because QA always finds more bugs anyway.
One of the best strategies I’ve found for avoiding getting stuck in the happy path is to plan out how you would test your code before you write it. You can’t get stuck only testing the way you meant your code to work if you haven’t written it yet :) You do need to have some idea how the feature as a whole is going to work, but if you don’t have that then you shouldn’t be worrying about testing anyway. Figure out what it’s supposed to do and then you can think about testing.
This works even if you’ve gotten as far as defining interfaces. Just take a minute and jot down some notes about what values could possibly get passed into those interfaces. Not what should be passed in, not what would ever be passed in by a reasonable human being who doesn’t personally hate you, but everything that the language itself would ever allow. This blog post On Testing is an extension of a joke tweet but is actually a great place to start if you’re not sure what sort of input you should be testing. And if you work in Java like me, make sure you handle nulls. Just because that parameter should never ever ever be null doesn’t mean you don’t have some messed up data somewhere in your system that will produce a nothing where there should be a something. And don’t forget to test with bad data so you can make sure errors are displayed when they should be and are spelled correctly.
If you do unit tests at your company testing thoroughly is a lot easier, but even if you don’t you can still manually test at least a few different cases. It’s just embarassing when you go to demo your new feature to someone and it immediately blows up.
Another part of testing, and for me the hardest part, is testing for my changes affecting existing code in non-obvious ways. It’s really easy to fix “surprise that parameter can be null” bugs and much harder to figure out why on earth adding a new feature would break an existing one that didn’t seem to be related. On the upside for developers like me, the entire reason regression testing exists is to catch bugs like this. Unfortunately, full regression tests aren’t feasible at every company for every release.
All I can really recommend to prevent the weird bugs is to isolate functionality as much as you can, which is good coding practice anyway. That is, if your app formats emails, all of the email formatting code should be in the same class if possible or the same package if you need more than one class. The less different features interact with each other, the less chance you have of those features getting in a fight :)
To bring this back to becoming a better developer, the fewer times QA (or god forbid, your customers) have to kick back a feature because it has bugs, the better a developer you are. Taking the time up front to make sure your code works is absolutely worth it for the time savings later and the increase in quality. Even if you deliver more slowly than programmers who do less testing, QA/your project manager/your team lead will notice whose features zip right through QA and whose get sent back over and over. And if they don’t, you should remind them repeatedly :) Going to QA first means nothing when it takes try after try after try to get approved.
One of the best things about testing thoroughly is that it’s a work thing you can do at work that doesn’t affect your personal time. It’ll even save you time in the long run!