• When/Then Unit Test Naming Pattern

    Published by Geoff Cox on January 16th, 2012 10:46 am under Practice of Software Development

    No Comments

    Giving meaningful names to unit tests is critically important to quality unit tests.  Unit tests classes often contain a large set of test methods and it can be challenging to distinguish from between tests because of the small permutations of the condition, the action, or the result.

    I was clued in to the When/Then naming pattern when working with Patterns & Practices at Microsoft.  I’ve seen this naming pattern work well across both client and web projects containing several hundred unit tests for all kinds of classes.  I’ve adopted for all my unit tests with success.

    The pattern

    When<ActionAndCondition>Then<ExpectedResult>.

    For example, a unit test that verifies the PropertyChanged event is raised when the Name property is changed might read:  “WhenNameSetToDifferentValueThenPropertyChangedRaised”.

    Benefits

    The When/Then naming pattern works well because it includes the action, condition, and result.  By putting the key semantic information in the name of the unit test there is no longer a need for method or code comments explaining what is being tested.

    The When/Then naming pattern has several other benefits.

    •    It naturally focuses each unit test on verifying one result.  This encourages writing atomic tests an discourages integration tests posting as unit tests.
    •    It helps evaluate the purpose of each member of a class by thinking about the conditions and results.  This also illuminates other unit test permutations.
    •    It helps describe the test independent of the code.  This helps when the test code doesn’t make the condition or result as obvious as the reader would like.  Most often this is due to mocking frameworks, verifying complex data, or other aspects of the test obfuscate the test’s purpose.

    Tips

    Some tips to consider when applying the pattern:

    •    To keep the names a little shorter, you can remove passive verbs.  “WhenNameIsSetToDifferentValueThenPropertyChangedIsRaised” becomes just WhenNameSetToDifferentValueThenPropertyChangedRaised.  At one point I was tempted to remove the “When” and the “Then” and separate them with an underscore, but I found that it made the test name harder to read for comprehension.
    •    Use standard verbs in your test names.  I use “Set” for properties, “Called” for methods, and “Raised” for events. I avoid synonyms like Updated, Recalculated, Invoked, or Fired.
    •    Often a set of tests are focused on single part of your class (such as the Name property).  I use #region to group test cases that are related.  This helps me avoid injecting excessive class structure into my test names and makes it easy to evaluate the set of tests when working toward 100% code coverage.

    Additional Examples

    Here are some additional examples from my own code:

    #region Name Tests

    WhenNameSetThenValueSet
    WhenNameSetToDifferentValueThenPropertyChangedRaised
    WhenNameSetToSameValueThenPropertyChangedNotRaised
    WhenNameSetToNullThenExceptionThrown
    WhenNameSetToEmptyThenValueSet

    #endregion

    #region UpdateStatistics Tests

    WhenUpdateStatisticsCalledThenTotalPriceSet
    WhenUpdateStatisticsCalledThenAveragePriceSet

    #endregion

    Tags: , , , ,

  • Leave a comment

    Your email address will not be published.