Friday, March 7, 2014

Abstract Principals For Writing Unit Tests

These abstract thoughts about writing clean tests, is the result of my "before and after" experiences with the Test classes.

Must Follow Principles

1. Boyscouting. Always leave the campground cleaner than when you arrived. If you have

to do anything to a test, make it cleaner, easier to read, than when you started.

2. KYK. (pronounced "kick") Keep Your Knowledge. This is an extended version of Boyscouting. If you have to dive deep enough into some code (unit-tests here, but this is true in general), to learn what it's doing -- don't throw that knowledge away! You will need it again. More importantly, someone else will need it. See the code as the next person will see it.

3. Use good names. A specific implementation of KYK. Once you know something about a method (class, object, field...), rename it so that knowledge doesn't disappear.

4. WTF's . the measure of code quality. How many times do you have to stop and (swear and) puzzle out what a test does?



5. Good tests assert the results of a calculation. Bad tests (which usually have lots of mocks) test... that the code we wrote, is the code that we wrote. Most of the tests (if we are mocking something) set up an expect that essentially injected a link object to be returned... and then asserted that the returned object was the one that was injected! Yes, it tested a little bit of the logic... but mostly it tested that injection works. Which we already knew.

6. DRY, DRY, DRY. Don't repeat yourself.

7. Short is beautiful. All other things being equal, shorter tests are easier to read, to work with, to fix, and to write... than long tests. Make your test methods short. Then make them shorter than that.

8. Comment if you must. Saving knowledge in a comment is better than letting it die. But even better is turning that comment into a method or field name. The best tests read like a series of english sentences.

9. Increase coverage. Remember many of your tests may be bogus (no asserts, replay() without verify(), etc.) [believe me it happens when you are working in a large team]
If you've been cleaning up a method, great! Now run a junit/emma "coverage as", and see what pieces of a method are not being covered. See if you can cover at least one such piece. (If you don't know how to measure coverage locally, install 'eclemma' in Eclipse. Or see me and I'll help you.)

10. Once you've cleaned up the test, clean up the code.  Sounds backwards?
Would you rather have obscure production code, or an obscure test? Give me a good, clean, test, and I can refactor the production code to make it clean. But if the test is hopeless, I can't do much of anything with the production code, except cross my fingers and pray.


I will be explaining each point in more detail in my next post with some actual examples of  writing good test cases.

Till then Comments/Suggestions are always welcome.

2 comments: