Nikola Anusev
Nikola Anusev

Reputation: 7088

How to organize unit tests and do not make refactoring a nightmare?

My current way of organizing unit tests boils down to the following:

Methods within each test class follow simple naming convention MethodName_Condition_ExpectedOutcome. So the class CustomerRepositoryTests that contains tests for a class CustomerRepository with a Get method defined looks like the following:

[TestFixture]
public class CustomerRepositoryTests
{
    [Test]
    public void Get_WhenX_ThenRecordIsReturned()
    {
        // ...
    }

    [Test]
    public void Get_WhenY_ThenExceptionIsThrown()
    {
        // ...
    }
}

This approach has served me quite well, because it makes locating tests for some piece of code really simple. On the opposite site, it makes code refactoring really more difficult then it should be:

Is there some clever way of organizing unit tests that would still allow me to locate tests for a specific code quickly and at the same time lend itself more towards refactoring?

Alternatively, is there some, uh, perhaps Visual Studio extension, that would allow me to somehow say that "hey, these tests are for that method, so when name of the method changes, please be so kind and change the tests as well"? To be honest, I am seriously considering to write something like that myself :)

Upvotes: 13

Views: 3381

Answers (5)

bryanbcook
bryanbcook

Reputation: 18393

Regarding VS extensions that associate code to tests, take a look at Visual Studio's Test Impact. It runs the tests under a profiler and creates a compact database that maps IL sequence points to unit tests. So in other words, when you change the code Visual Studio knows which tests need to be run.

Upvotes: 1

user1494736
user1494736

Reputation: 2400

After working a lot with tests, I've come to realize that (at least for me) having all those restrictions bring a lot of problems in the long run, rather than good things. So instead of using "Names" and conventions to determine that, we've started using code. Each project and each class can have any number of test projects and test classes. All the test code is organized based on what is being tested from a functionality perspective (or which requirement it implements, or which bug it reproduced, etc...). Then for finding the tests for a piece of code we do this:

[TestFixture]
public class MyFunctionalityTests
{
    public IEnumerable<Type> TestedClasses()
    {
        // We can find the tests for a class, because the test cases references in some special method.
        return new []{typeof(SomeTestedType), typeof(OtherTestedType)};
    }

    [Test]
    public void TestRequirement23423432()
    {
        // ... test code.
        this.TestingMethod(someObject.methodBeingTested); //We do something similar for methods if we want to track which methods are being tested (we usually don't)
        // ... 
    }
}

We can use tools like resharper "usages" to find the test cases, etc... And when that's not enough, we do some magic by reflection and LINQ by loading all the test classes, and running something like allTestClasses.where(testClass => testClass.TestedClasses().FindSomeTestClasses()); You can also use the TearDown to gather information about which methods are tested by each method/class and do the same.

Upvotes: 4

Frank Schwieterman
Frank Schwieterman

Reputation: 24478

One way to keep class and test locations in sync when moving the code:

  • Move the code to a uniquely named temporary namespace
  • Search for references to that namespace in your tests to identify the tests that need to be moved
  • Move the tests to the proper new location
  • Once all references to the temporary namespace from tests are in the right place, then move the original code to its intended target

One strength of end-to-end or behavioral tests is the tests are grouped by requirement and not code, so you avoid the problem of keeping test locations in sync with the corresponding code.

Upvotes: 1

HatSoft
HatSoft

Reputation: 11201

Is there some clever way of organizing unit tests that would still allow me to locate tests for a specific code quickly

Resharper have some good short cuts that allows you to search file or code

As you said for class CustomerRepository their is a test CustomerRepositoryTests

R# shortcut shows inpput box for what you find in you case you can just input CRT and it will show you all the files starting with name have first as Capital C then R and then T

It also allow you do search by wild cards such as CR* will show you the list of file CustomerRepository and CustomerRepositoryTests

Upvotes: 0

Shiraz Bhaiji
Shiraz Bhaiji

Reputation: 65491

One unit test project per project is the way to go. We have tried with a mega unit test project but this increased the compile time.

To help you refactor use a product like resharper or code rush.

Upvotes: 0

Related Questions