Naming conventions for tests in C#

So, you’re writing automated tests (hopefully). Maybe your team can’t agree on how to name tests, or maybe you’re working solo and not sure the idioms other people are working with. Plus, naming tests can be hard, and following some guidance can be helpful in figuring out good test names.

In my opinion, good test names really only need to satisfy two things:

  1. Clearly state what the test doing
  2. The whole team agrees on doing it that way

Aside from that, there’s a lot of freedom in choosing what you like best. I don’t really want to make it sound like I endorse or dislike any of these options, either. I have my own preferences, but I think these are all fine choices.

That being said, if you’re curious, I currently use #2.

 

1. UnitOfWork_StateUnderTest_ExpectedBehavior

This pattern was suggested by Roy Osherove in his book, The Art of Unit Testing, first published in 2006. Usually, the unit of work will be a method name, but it doesn’t necessarily have to be.

Example: AddProduct_ProductNameExists_ThrowsException or AddProduct_ProductNameDoesNotExist_Succeeds

 

2. Given, when, then

This is a BDD-style naming convention, and works just as well for plain old non-BDD tests. While the “given” part can be part of the test name, it’s often stated in the name of the test class (or subclass), since that precondition applies to all tests inside of the class. See more info in Martin Fowler’s post.

Example: Given_ProductDoesNotExist_When_AddProduct_Then_ThrowsException

 

3. Plain old English with underscores instead of spaces

As far as I know, this doesn’t have any kind of name, but I think it’s a viable option. While I would like if C# could do what some other languages do and use actual strings for the test names, this is pretty close. You can also just use one of the other options with this, as well, such as with given, when then.

Example: Adding_A_Product_That_Doesnt_Exist_Throws_An_Exception

 

4. xUnit’s DisplayName

xUnit’s DisplayName allows us to use a string for the test name, which let’s us use normal English for test names. This is similar to the above in that we can use it with another naming style, such as given, when, then.

Note that a potential caveat here is that you now need to decide what to do with the actual function name. We can see one option in the real world from bUnit, a Blazor testing library (just search the repo for “DisplayName”). That repo uses DisplayName for the test names, then just names the actual functions things like Test001().

Example: [Fact(DisplayName="Given the product does not exist, when AddProduct is called, throw an exception"]

 

5. xUnit’s config file

This is one I’ve not messed with, just because it never seemed worth the hassle. However, maybe others have found it useful.

xUnit’s xunit.runner.json config file allows you to do many things, including specify how the method names for tests will be displayed when you run them. I won’t detail how to do that here, but it allows you to use spaces and special characters in test names.

For instance, with replaceUnderscoreWithSpace and useOperatorMonikers, transformations like the following are possible:

Method name: When_product_cost_is_ge_100_then_add_discount()

Displayed test name when ran: When product cost is >= 100 then add discount

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top