Recently I was asked to draw ups some guidelines regarding Unit Testing. I was hoping to find something that I could point people to, but I didn’t find any one listing that I liked. So, I’ve drawn up my own Unit Testing Guidelines / Commandments / Rules Of Thumb / Principles / Heuristics / Best Practices / Whathaveyous:
Tests should be written first
Let the test help direct the design
Make the code easy to test
Each test must be independent of other tests
Running tests in isolation provide faster feedback and makes testing easier
Junit assumes that tests can be run arbitrary order
Depending on other tests indicates tightly coupled code
Tests should not be dependent upon upon production code to be tested
For example, don’t use your dao to insert data for testing
Failing to do so requires proving that the dao works, which then creates a dependency on another test
Tests should demonstrate behavior for expected and unexpected behavior
Tests serve as documentation for the happy path and the sad path
Red, Green, Refactor
This is where we remove duplication, simplify, and in general make things better
Applies to the test code as well
Each class merits its own test class
Applies to “simple” classes, too
Not only is it a test, it is documentation for the future
Organize test methods in three chunks arrange, act, assert
This makes your intent much easier to understand
Isolate layers
You shouldn’t need a database connection to test a class that doesn’t directly use the database
Mocks, Stubs, and Dependency Injection are your friends
Each test method should test one thing
This makes your intent much easier to understand
This makes it easier to understand what is and isn’t working
Ideally it would have one assert
Prefer naming conventions that describe the scenario and outcome
One example is methodName_Scenario_Outcome
Use the language of the domain
Know what you are testing and how to test it
Prefer state-based testing for checking return values and outcomes
Prefer behavior-based testing for testing interactions
Keep tests as quiet as possible
Avoid printing out statements, logging, etc.
Your tests should only be vocal when something interesting (usually bad) happens
Tests should be as small and as fast as possible
Do one thing, do it fast
Fast feedback is the name of the game
Tests should be run regularly
In the very least, every time there is a code change
Automate it
Get notifications if tests are failing
Fix tests ASAP
Even if you aren’t the on who created the issue
Write tests to reproduce bugs
Use this to guide fixing code.
Obviously, this isn’t the alpha and the omega of unit test practices, but I think it captures most of what’s critical.
The following links were influential (but not the only influence) for this list.
http://exubero.com/junit/antipatterns.html
http://geosoft.no/development/unittesting.html
http://stackoverflow.com/questions/106800/unit-testing-guidelines
http://blog.jayfields.com/2005/11/unit-test-guidelines.html
http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/UnitTesting/1-Articles/UTGuidelines.html No Longer Valid
http://pragprog.com/the-pragmatic-programmer/extracts/software-entropy
http://www.robertbeal.com/145/thoughts-about-unit-testing-private-methods-and-100-coverage
http://martinfowler.com/articles/mocksArentStubs.html