1

I am new to unit testing, but finally getting started.

I have been running into a situation where my unit test names apparently grow too long to readable due to the multiple parameters and combinations of them. For example, consider these hypothetical test case names resembling my actual test case names:

GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsFinanceAndDesignationIsManager_AccessAllowed
GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsFinanceAndDesignationIsAnalyst_AccessDenied
GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsFinanceAndDesignationIsTemp_AccessDenied

GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsHrAndDesignationIsManager_AccessAllowed
GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsHrAndCorpConselor_AccessDenied
GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsHrAndDesignationIsTemp_AccessDenied

GetAllEmployeeRecords_UserDoesNotBelongToHeadQuarter_AccessDenied

I feel that the UserBelongsToHeadQuarter phrase in the names is redundant for the 6 out of 7 test cases but it is also important to distinguish the 6 tests from the 7th test.

Using a [TestCategory] might work but my team members have concerns that failing test case might have difficulty communicating what exact scenario is failing on test execution reports and/or the [TestCategory] is more suitable for breaking down the tests by component or feature.

Is there a better way to organize or name these for more readability?

I looked up unit test practices at Microsoft page or in NodaTime code base but I don't find any longer names.

4
  • 1
    The test name doesn't have to describe the complete scenario as long as its purpose is recognizable. A shorter test name like _AllowFinanceManager would likely work just as well. Of course, data driven approaches as suggested by Ewan make it completely unnecessary to come up with names for what are effectively just different instances of the same test case.
    – amon
    Commented Jan 11, 2019 at 11:36
  • 1
    You can move tests of GetAllEmployeeRecords method into dedicated file, then name of the method can be dropped from the test name. Data driven approach will save space and time to understand/read test cases.
    – Fabio
    Commented Jan 11, 2019 at 18:47
  • Sidenote: possibly helps if you could use a test framework where tests are specified by strings, rather than by function names. This gives you much more expressive power for naming
    – DarkTrick
    Commented Jan 5, 2023 at 4:44
  • I cases like that I tend to use a hierarchical test structure: GetAllEmployeeRecords { UserBelongsToHeadQuarter { ... } , UserDoesNotBelongToHeadQuarter { ⇒access_denied() ... } }. Each step in the process is a new level; each parameter is a new element inside a level
    – DarkTrick
    Commented Jan 5, 2023 at 4:46

2 Answers 2

4

Have a look at Data Driven Tests

Essentially you can refactor your tests to something like :

["sales", 34] 
["finance",12] 
GetEmployeeTest(string dept, int
expectedCount) { ... }

The test framework will pass in the parameters from the data block and name the tests accordingly so you can see them in the results.

2

Refactoring

The long name implies that you have a complicated scenario. This is a code smell. Is it possible to refactor the code that you are testing that can simplify it?

If you can simplify it, you will also simplify the complexity of the scenario.

Modules

Sometimes the tests have to be complex because the system can't be simplified for whatever reason. That in itself is a code smell, but lets say that the decision has been made for you. You can use test Fixtures, or files, or modules whatever abstraction mechanisms your language has to group tests with related setup together.

class GetAllEmployeeRecords_UserBelongsToHeadQuarterAndDeptIsFinance_Fixture
{
    void SetUp();

    void DesignationIsManager_AccessAllowed();
    void DesignationIsAnalyst_AccessDenied();
    void DesignationIsTemp_AccessDenied();
}

This provides a simplification to naming, but also allows for the common state to be setup once in the SetUp() function.

Unit Tests vs Integration Tests

The final problem that I can infer is that these are not Unit Tests. A Unit test is really a very simple check.

void GetAllEmployeeRecords_WithAnAuthenticatedUser_ReturnsRecords()
void GetAllEmployeeRecords_WithANonAuthenticatedUser_ReturnsInvalidUser()
  • We don't care who is an authenticated/not-authenticated user.
  • We care that the method when called with an authenticated user returns records
  • We care that the method when called with a non-authenticated user returns invalid user

What you have, appears to be an Integration Test. In an integration test a number of collaborators are configured with data, and the they are asked to co-operate to produce the end result.

In this case, you appear to be configuring the security sub-system, with the api end point, and any data the api needs to process a request. Then you are making a request to ensure that the system: Authenticates, Handles, Selects the correct data, and responds correctly.

Integration tests are much harder to write, tend to break more easily, and take longer to run. They are useful, and good to have but they don't provide the same quick responses that a unit test does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.