1.- Write a test case for every condition.
There’s a common misunderstanding- some developers translates “one test case for every condition” to “one test case for assertion”, that’s just plain wrong, a condition can contain one or more assertions, check the following test case.
As you can see, only one condition is tested and it’s composed of many assertions. When you are picking the condition to test, it is also a good idea to focus on the boundaries of your system, so if you are testing a range, try testing with the last element of your range, the first element…
2.- Test only one thing .
If you don’t write your tests to only test one thing, you may find the following problems.
- Over complicated tests. Tests which are difficult to understand.
- Overlapping tests. Different tests testing the same functionality, this will carry a lot of overhead when you will have to maintain them.
- Low code coverage. Is easier to have higher code coverage if you write simple test cases for all the elements of your code.
- Difficulty to track an error. When your test cases fail, ideally it should be pretty straight forward to tell where they are failing. When you are testing several things in every test case is hard to tell what the source of the errors is.
To test only one thing is sometimes hard because of the dependencies in your system. You may want to write a test case for a class that indirectly uses a database, or a third class, in this case, the best solution is to use a mock, stub or a fake object.
3.- Make the test case describe how your system works.
Test cases should be used as well as documentation on how your system works, they will tell the user how can you use the interfaces of the different classes and what kind of errors can you expect. A few tips to help creating test cases that self document your code are:
- Write your own asserts, for instance, you can see the custom assert I wrote for the chess test case example above.
- Make clear the 4 stages of every test case: Setup, Exercise, Verification and Tear down
- Make your test code as clean as your production code.
4.- Organize your test cases consistently.
There are several ways to organize your test cases, by class, functionality… Whatever the structure you pick, just keep the consistency so it will be easy to locate and add new test cases in the future.
5.- Make “FIRST class” test cases (Fast, Independent, Repeatable, Small and Transparent)
- Fast. Your test cases should be very fast to execute, every time you want to run all of them it shouldn’t take more than a few seconds for an small application.
- Independent. You should be able to run your test cases in any order.
- Repeatable. The result of the test case should be always the same, no matter how many times you have executed it before.
- Small. Small test cases are easy to understand and change, are also likely to be faster.
- Transparent. It should be clear what the purpose of each test case is.