UnitTestGoodPractice
From MantidProject
Contents |
What to test
Simply put you should test.
- Every public member of a class.
- That the class can be cast to any of the interfaces or base classes it inherits from.
- Any private or protected members.
- That aren’t directly covered by a public method test.
- That do any significant processing.
For each method you are testing you should include tests for the following:
- To confirm that the methods meet the requirements associated with them. Thus the test should verify that the function does what it is supposed to do.
- To confirm the expected behaviour for boundary and special values.
- To confirm that exceptions are thrown when expected.
How to test private or protected members of a class
Testing the internals of a class can be considered harmful as it exposes the internals of the class, which can arguably be freely changed (so long as it does not affect the function of the public interface). However there are cases where the internals of a class need unit tests either due to complexity or tracking down specific bugs.
Protected
Within the test library you can add a new testable class that inherits from the class you need to test. This class can simply expose any protected methods as testable public methods.
Private
There is no ideal way to test a private member of a class as they are intentionally hidden from the class interface. There are two options to consider in preference order:
- Change the protection level to protected and follow the approach above.
- Declare the test class as a friend, which can access private members.
Good practices for writing tests
The following are good practices for writing your unit tests. Many of them are standard good coding practices. You will notice that in several situations they can clash with each other, in this case common sense needs to be applied.
- Unit tests should test one method only. This allows you to easily identify what failed if the test fails.
- Unit tests should not be coupled together, therefore one unit test should not rely on another unit test having completed first.
These two often clash, in which case it is often better to compromise on the first.
- Units tests should use realistic data
- Unit tests should use small and simple data sets.
Again these can often conflict.
- Each test class should be named after the class it is testing (e.g. tests for the AlgoithmFactory should go in a AlgorithmFactoryTest class).
- Each test within a test class should use a descriptive test name, prefixed with test (tests for the CreateAlgorithm method would be included in testCreateAlgorithm). If there are specific tests for failure situations then these should be added to the end (e.g. testCreateAlgorithmNoAlgorithmException). The aim is that from the test method name alone you should be able to identify the problem.
Tests should be fast, ideally really fast - certainly not more than a few seconds.
