Rules to Better Unit Tests

Enhance your software quality with these essential rules for unit testing. From understanding the importance of unit tests to leveraging effective testing tools, these guidelines will help you create robust tests, isolate your logic, and ensure your applications perform as expected.

  1. Customers get cranky when developers make a change which causes a bug to pop up somewhere else. One way to reduce the risk of such bugs occurring is to build a solid foundation of unit tests.

  2. Some people aim for 100% Unit Test Coverage but, in the real world, this is 100% impractical. Actually, it seems that the most popular metric in TDD (Test-Driven Development) is to aim for 100% of the methods to be unit tested. However, in practice, this goal is rarely achieved.

    Unit tests are created to validate and assert that public and protected methods of a class meet an expected outcome based on varying input. This includes both good and bad data being tested, to ensure the method behaves as expected and returns the correct result or traps any errors.

  3. It's important that the unit tests you develop are capable of failing and that you have seen it fail. A test that can never fail isn't helpful for anyone.

    This is a fundamental principle in Test Driven Development (TDD) called Red/Green/Refactor.

  4. When you encounter a bug in your application you should never let the same bug happen again. The best way to do this is to write a unit test for the bug, see the test fail, then fix the bug and watch the test pass. This is also known as Red-Green-Refactor.

    Tip: you can then reply to the bug report with "Done + Added a unit test so it can't happen again"

  5. There are three main frameworks for unit testing. The good news is that they are all acceptable choices:

    • They all have test runner packages for running tests directly from Visual Studio
    • They all have console-based runners that can run tests as part of a CI/CD pipeline
    • They differ slightly in syntax and feature set
  6. Check out these sources to get an understanding of the role of unit testing in delivering high-quality software:

  7. A Continuous Integration (CI) server monitors the Source Control repository and, when something changes, it will checkout, build and test the software.

    If something goes wrong, notifications are sent out immediately (e.g. via email or Teams) so that the problems can be quickly remedied.

  8. Test Projects

    Tests typically live in separate projects – and you usually create a project from a template for your chosen test framework. Because your test projects are startup projects (in that they can be independently started), they should target specific .NET runtimes and not just .NET Standard. A unit test project usually targets a single code project.

    Project Naming

    Integration and unit tests should be kept separate and should be named to clearly distinguish the two. This is to make it easier to run only unit tests on your build server (and this should be possible as unit tests should have no external dependencies). Integration tests require dependencies and often won't run as part of your build process. These should be automated later in the DevOps pipeline.

  9. A test verifies expectations. Traditionally it has the form of 3 major steps:

    1. Arrange
    2. Act
    3. Assert
  10. By difficult to spot errors, we mean errors that do not give the user a prompt that an error has occurred. These types of errors are common around arithmetic, rounding and regular expressions, so they should have unit tests written around them.

per page
1 - 10 of 23 items
We open source.Loving SSW Rules? Star us on GitHub. Star