Unit Test Best Practices and Guidelines

The following are Unit Test best practices and guidelines:

  1. Test one object or class per unit test class.
    Yes, you should refactor your code if you cannot test one class only.
  2. 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.
  3. 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.
  4. 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 your check in code and your build kicks off. You should be automatically notified if any code you wrote breaks an existing Unit Test.
  5. 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.
  6. 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:
    FunctionX_True_Test()
    FunctionX_False_Test()
    Think of it this way. When a test fails, you should know exactly what failed and why just because of the function name.
  7. 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.
  8. 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.
  9. 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

3 Comments

  1. DCook says:

    I'm just beginning unit testing for a large software project. We don't have enough programming time to write all the unit tests to test all the classes.
    I think you are advising in best practices not to combine different classes in one test.
    However, most of our bugs occur in the interaction between classes. Will we be able to handle interactions between classes in unit testing? (Forgive me for this question which you may have already answered in later sections of your excellent tutorial)
    It seems you advocate starting out by testing each class function separately. I despair of ever catching up with the development this way. Instead, I am starting by unit testing the functions that are most critical or have generated the most bugs. I then started thinking of the entire application and finding there are some core features that need testing. I wondered if I could focus on just the classes needed for these features. Especially when the code is now stable and relatively bug free, if I can get the unit tests written before we need enhancements to these stable procedures, it would help because we will know if we break them. I am somewhat overwhelmed because I keep feeling that my unit tests are worthless unless I can get significant coverage of a one of our product's features. So when I start to write a unit test for a function I know gets rarely called, I want to skip that and just focus on the important tests.

    • Rhyous says:

      DCook,

      Life isn't always perfect. Sounds like you are in the "test what you can" phase.

      If you are testing more than one unit, it is still a valid test, it is just not called a unit test. A unit test tests one unit.

      Yes. Some people call a test that interacts with two classes "Interaction Tests" or "integration tests". Same rule applies for naming. Name the project "MyProjectIntegrationTests".

      If you were to do Unit Tests correctly, anywhere where you think you have to test two objects together, object1 and object2, you would replace object2 with an interface, mock the interface, and assert that object1 correctly makes the calls to ojbect2. Then you unit test object2 to make sure it functions correctly.

  2. ebi says:

    Good Job friend. Really helpful.

Leave a Reply

Powered by sweet Captcha