The following are Unit Test best practices and guidelines:
- Test one object or class per unit test class.
Yes, you should refactor your code if you cannot test one class only.
- Name your test class after the class it tests.
If you have a class named SomeClassY, then your test class should be named SomeClassY_Tests.
- Perform one test per test function.
The test class can have as many functions as you need. Perform one test per function. That doesn’t mean one Assert call. Multiple assertions might be needed to perform one test. Think of it this way. When a test fails, you should know exactly what failed and why just because of which test function failed.
- A unit test should run on the Build and Continuous Integration (CI) systems.
Unit tests are there to help you succeed and prevent you from failing. If they run rarely, they rarely help. They should run every time you check in code and every time your build kicks off. You should be automatically notified if any code you wrote breaks an existing Unit Test.
- A unit test should never alter the system in any way.
Don’t touch files, databases, registry, network, etc… A test that does so is a functional test not a Unit Test. If an object cannot be tested without touching the system, refactor the object to use an Interface (and if needed a wrapper) for interacting with the system so such can be faked, or mocked with a tool such as RhinoMocks or MOQ. This is important because if a Unit Test is running on the Build or CI system, you could actually introduce a change to the system that hides a bug and allows the bug to exist in a released product.
- Make the test function names self documenting.
This means if you want to test passing in a bool to FunctionX you might call your test functions something like this:
Think of it this way. When a test fails, you should know exactly what failed and why just because of the function name.
- Never assume 100% code coverage means 100% tested.
For example, 100% coverage of a function that takes a string as a parameter might be 100% tested with one test. However, you may need to test passing in at least five string instances to avoid all types of bugs: expected string, unexpected string, null, empty, white space, and double-byte strings. Similarly a function that takes a bool parameter should be tested with both true and false passed in.
- Test in the simplest way possible.
Don’t elaborate, don’t add extra code. Just make a valid test as small as possible. Warning! That doesn’t mean you can forget the best practices and guidelines above. For example, if the simplest way is to test everything in one function do NOT do it. Follow the best practices and guidelines.
- Get training and keep learning about Unit Testing.
You won’t do it correctly without training and continued learning. It doesn’t matter if you do your own research and train yourself by reading online articles, blog posts, or books. Just get yourself trained and keep learning. There are many test frameworks, mocking frameworks, wrappers (such as System Wrapper), and encapsulation issues, and without training you may end up with Unit Tests that are not maintainable. You will find many opinions about best practices, some matter, some don’t, but you should know each side of the opinions and why those opinions exist whether you agree with them or not (this list included).
I hope this list helps you.
If you have a best practice not on this list, or you want to comment on one of the items, or even disagree, please comment.
Return to C# Unit Test Tutorial