Brendan Enrick

Daily Software Development

Unit Testing With a Base Test Class

Writing good code that can be trusted to work means unit testing your code. In order to effectively maintain these tests you will need to follow the same principles you would with any other code. This of course means that you extract logic to achieve code reuse, name methods and objects clearly, use composition, and use inheritance.

In this post I am going to show how you can get some code reuse when you’re following another good testing practice. You should keep things well abstracted. I like to keep my tests in folders and I keep test classes in those folders. I do this so that I can have each test class be small and only be testing one things. By doing this I make my test classes a lot cleaner and easier to work with. This means, however, that if I do not extract some of the duplication I could be creating more maintenance work later.

On way that I keep my tests more maintainable is to keep duplicated logic for initialization in base classes. When I am testing methods of a certain class, I will keep a folder of those tests and have a class for each area of the code I want to test. This lets me keep some of the initialization logic in a base class. Many of the test classes will need an instance of the object being tested, so I can put logic in the base class to initialize my mock objects pass them to the constructor of the class I will be testing.

Setting up a base class is easy. The following examples show how to set up a base test class in MSTest and NUnit.

Setting Up a Base Test Class with MSTest

[TestClass]
public class BaseTestClass
{
public BaseTestClass()
{
Console.WriteLine("BaseTestClass.Ctor()");
}

[TestInitialize]
public void BaseTestInitialize()
{
Console.WriteLine("BaseTestClass.BaseTestInitialize()");
}

[TestCleanup]
public void BaseTestCleanup()
{
Console.WriteLine("BaseTestClass.BaseTestCleanup()");
}
}

[TestClass]
public class ConcreteTestClass :BaseTestClass
{
public ConcreteTestClass()
{
Console.WriteLine("ConcreteTestClass.Ctor()");
}

[TestInitialize]
public void MyTestInitialize()
{
Console.WriteLine("ConcreteTestClass.MyTestInitialize()");
}

[TestCleanup]
public void MyTestCleanup()
{
Console.WriteLine("ConcreteTestClass.MyTestCleanup()");
}


[TestMethod]
public void TestMethod1()
{
Console.WriteLine("ConcreteTestClass.TestMethod1()");
}

[TestMethod]
public void TestMethod2()
{
Console.WriteLine("ConcreteTestClass.TestMethod2()");
}
}

MSTestBaseClassTestOutput

BaseTestSessionOutput

Setting Up a Base Test Class using NUnit

[TestFixture]
public class BaseTestClass
{
public BaseTestClass()
{
Console.WriteLine("BaseTestClass.Ctor()");
}

[SetUp]
public void BaseSetUp()
{
Console.WriteLine("BaseTestClass.SetUp()");
}

[TearDown]
public void BaseTearDown()
{
Console.WriteLine("BaseTestClass.TearDown()");
}
}

[TestFixture]
public class ConcreteTestClass : BaseTestClass
{
public ConcreteTestClass()
{
Console.WriteLine("ConcreteTestClass.Ctor()");
}

[SetUp]
public void SetUp()
{
Console.WriteLine("ConcreteTestClass.SetUp()");
}

[TearDown]
public void TearDown()
{
Console.WriteLine("ConcreteTestClass.TearDown()");
}


[Test]
public void TestMethod1()
{
Console.WriteLine("ConcreteTestClass.TestMethod1()");
}

[Test]
public void TestMethod2()
{
Console.WriteLine("ConcreteTestClass.TestMethod2()");
}
}

NUnitBaseClassTestOutput

BaseTestSessionOutput

Notice in these examples how the Base method setups happen first and then the local class ones. This allows you to depend on the code happening on the base class first. Then when you tear everything down you will first clear up things in the local method and then the base class will run.

Make sure you follow this example by having different names for the base methods so they don’t collide with the local names. This lets you have them both run without one having to call the other. If the names match you will either be overriding the base or hiding it, but they will not both run.

Test Driven Development is Very Approachable

Othello_board Growing up I always enjoyed a good game of Othello. The rules of the game are very simple, but it takes a lot of work to become really good at Othello. There is a great tagline used to describe this game; “A Minute to Learn...A Lifetime to Master”.

The same can be said about Test Driven Development. In fact, when NimblePros hires interns in the summer, we go to recruiting events and set up laptops for people to write some code using TDD. When there are no students in the room, we’re the ones working on the code. Even our seasoned developers need to practice using TDD or we’ll never become better at using it.

The great part about this is that you don’t need any experience with TDD in order to sit down and start. You don’t want to sit down and start using TDD on legacy code, but simpler problems are a great way to get started.

We like doing these exercises as it allows us to not only see who can write code, but also who is willing to take the leap and try new things. This is one of our self-selecting techniques of evaluating people. Would you hire an employee not willing to go out on a limb and try something new? I wouldn’t.

I have two points to make: it’s easy to get started with TDD and if you don’t practice it you’ll never master it.

Sure, I can grab students from a college who may have only heard of unit testing in a class and have never really implemented it, but will those students ever get good at TDD. I think that they will if they work hard and actually use TDD. You have to practice it though. TDD will slow you down at first, which is why you need to practice it.

Time-Tested Testing Tips - Part 3

Context switching is very costly and this same issue can be seen when writing tests, but I would argue most importantly in maintaining and reading tests.

There are three main parts to a test. The first part sets everything up, the second part takes some action, and the third part expects certain results given the the start and the action taken. In this tip I'll be talking about the first part, the setup.

Keep Test-Relevant Details Visible

I've said in the past to treat test code just like any other code. However, there are a few reasons to break from this rule. One is the context switching which will be caused by extracting information which is important to a test. Let me explain what I mean with two examples.

Example Using Helper Method

[Test]
public void CalcInterestRoundsToTenthPennies()
{
    decimal initialMoney = 100.00;
    decimal expectedInterest = 33.333
    InterestCalculator ic = GetTestInterestCalculator();
    
    decimal actualInterest = ic.CalcInterest(initialMoney);
    
    Assert.AreEqual(expectedInterest, actualInterest, 
      "CalcInterest did not round to a tenth of a penny correctly");
}

Example Without Helper Method

[Test]
public void CalcInterestRoundsToTenthPennies()
{
    decimal initialMoney = 100.00;
    decimal interestRate = 0.3333333333;
    decimal expectedInterest = 33.333
    InterestCalculator ic = new InterestCalculator(interestRate);
    
    decimal actualInterest = ic.CalcInterest(initialMoney);
    
    Assert.AreEqual(expectedInterest, actualInterest, 
      "CalcInterest did not round to a tenth of a penny correctly");
}

Notice here that you can tell a lot more about what is going on in the second one, because you know what percentage is being used to calculate. You cannot tell that the first one is accurate since you can't see the percent. I recommend trying to keep the amount of values to a minimum and if you're writing your code well you'll have few enough dependencies that you will not have a problem. These helper methods as you can see make it so you will need to go to another location to see what was initially created. In some instances they are useful, but use them sparingly as they might hide away details.

Do Not Unit Test Third Party Frameworks

Make sure that what you're testing is part of your code and not someone else's. If you're testing code you have no access to you better not be keeping that around as an automated test. You're wasting your time if you're creating automated tests for this code. If you find a bug in the code you can tell someone about it, but you probably can't fix the code. If it is an open source project you're testing then go test the code in their test library and fix issues you find. You will be doing them and yourself a favor. Don't clutter your own test library.

Write Automated Tests Whenever You Are Curious

If I ever wonder how some piece of code or a class works or something, I could go write a simple application and test something out. I certainly do not waste my time though. It tends to be much faster just to write a test to answer my question or learn something new. If I want to try something out I just write a test. If it is an internal piece of code I go look at the existing tests, and if it is not I write a temporary one just to try something out.

Unit tests are quite useful for this sort of thing, and since I have keyboard shortcuts mapped to run them they're very fast. If you really want to test a lot, you need to start using them all the time. They become very easy to come up with and write once you practice them enough.

Time-Tested Testing Tips - Part 2

In the first part of this series of testing tips, I mentioned a couple of tips I believe to be quite useful. I am going to continue this series today by writing about a couple of more ways to write better tests. I also plan to give reasons for testing and describe different benefits of the practice as I go.

Test Driven Development

Yes, I am going to bring this up. Plenty of people have latched onto the idea that testing code helps make code better. A lot of people even believe that it makes the process of writing the code faster. I see a lot of people who are reluctant still to use test driven development. I know I am throwing around a buzzword… or maybe I mean buzzphrase since that’s actually three words.

I don’t plan on doing TDD justice here since I am trying to keep these tips relatively short. I just hope this is enough to inspire people to go read, learn more, and try some test driven development. I am going to give some quick reasons why developers testing their code should write the tests first.

  • You will not want to go back and write it later. Sometimes you are going to go back and write the tests for the code you have already written, but what happens if you decide you’re going to write a lot of code and then go back and add the tests. Now you’re talking about a lot of testing all at once. There is a good chance you’ll cut corners and maybe skip entire aspects of the testing. I know I would be tempted.
  • How do you know what kind of interface your new code needs if you’ve never used it? If you start by trying to use some code that does not exist yet, you’ll be deciding how you would want to use it. Now you’re probably thinking you could do that anyway. If you write code to use some new feature you will know the design is easy to use and work with. You just made it up and used it in the test. If you didn’t write the test you had to guess what interface you will want later.

Organize, Refactor, and Take Care of Your Tests

I recommend you repeat this daily, “My test code is just as important as my production code”. I think this is a very good point to remember when you’re writing tests. All of those principles you apply when writing production code should be followed with test code. DRY, SOLID, YAGNI, etc. are all important even with the testing code.

Obviously duplicating code can make your tests difficult to maintain. What if some business logic changes? If you were repeating yourself you now have the fun task of going through a dozen tests changing each one, but if you had not repeated the same code you might have been able to update one location in the test code. A lot of people are concerned when the line count of a single file gets large and they will refactor it into multiple manageable files. This same policy should apply to test classes. If you’ve ever gone into a test class with way too many classes, you probably know how difficult it can be to maintain.

Tests exist to make development easier, and if they become difficult to maintain then something needs to change. I certainly don’t advocate spending large amounts of time refactoring the tests, but since they are supposed to increase the longevity of the application they must also be maintained.

Adjust Your Style to Your Test Framework

I obviously recommend that everyone use a testing framework. There are plenty of them out there, and they supply a great deal of the tools you’ll need for testing. They come in all languages, flavors, and colors. You might look into these NUnit, MSTest, JUnit, CppUnit. What is important is that you make sure you know how your tools work so you can test best with them.

I will elaborate on a couple of examples and perhaps down the road I’ll give some more specific examples.

Some tools show you a list of test names, and only minor details about why the test failed. For this you usually need to go the a description view or something similar. In these cases it is important to name your tests effectively.

As an example if I have a method called Add and it takes two parameters a and b. I might write a test for that method. If I name my test TestAdd, and that test fails you know something is wrong in that method, but you do not know what failed. If I had instead made a few more specific methods you could glean more information from the test having failed. Some examples of tests I might create are AddTwoZerosShouldBeZero, AddNumberToZeroShouldBeTheNumber, AddPositiveNumbersTest, AddNegativeNumbersTest, etc.

Some parts I would lump together like positive numbers and negative numbers. It is important to handle a couple of different scenarios as well as the edge cases. I could have done negative and natural numbers and that would cover all numbers, but I wanted to make sure the edge case, zero, was handled correctly, so I test it separately.

People can argue back and forth all day long about whether you should have a lot of small tests or group them together, but this is what has worked well for me in the past and I hope it works well for you also.

Treat Your Tests Well

There are a lot of people starting to test, and some of them seem to have this misconception that test code is less important because it is, "just test code". I don't know how they come up with this crazy idea, but it creates some pretty ugly tests. When following the principles of Test Driven Development, it is important to realize that you will come back to these tests. You will look at them when they fail, you will adjust them when logic changes, and others will read them especially when they are trying to learn the system.

Maintenance

At some point you could perform maintenance on any piece of code in your application. THIS INCLUDES YOUR TESTS. When you need to go in and change them it better be easy. There better be code reuse, variable names better be descriptive, and you really need to have things organized well enough for you to find what you're looking for.

Single Responsibility Principle

The Single Responsibility Principle is a commonly followed principle when writing code, but I've seen people disregard it when writing tests. Your tests are extremely important. Don't make huge catchall test classes. Keep your test classes small and manageable. Each one should contain only a related group of tests. You will come back to these if you're testing correctly, and when you make changes you will write new tests or adjust old ones. Don't think for one second that you will never see your test classes after you write them. When you add new features and adjust old ones, you will need to open these files again.

Test code is a first class citizen in your project. It is every bit as important as the rest of the project. Treat it as such or it will bite you back.

One Way Tests Differ From Other Code

With tests, the specific details are a little bit more important than in other code. You still need code reuse for obvious reasons, so what do I mean here? All I am saying is that you don't want to hide things away in mysterious methods. Normally we extract methods to hide the details of some operation we are performing. We should be doing the same thing with test code, but we need to make one exception. When the details of that method are what you're testing, you must have them in your test.

In some instances you have an object with involves some complicated or at least tedious initialization, so you would want to hide that away in a method. For testing, however, it is important that you define the details of that initialization in the test method if they are important to the test.

As an example, we can say that we are working on a game, and we keep a Points property on our Player object. Maybe we want to make sure that after some action that would lose a player points, he doesn't go below a negative number. So we have a method that creates a player object for us. The problem is that we don't know what his initial points are set to if we don't either make that a parameter in the initialization method or set it after initialization. In some way we need to make sure that we define this in our test method.

Never ever let details you depend on be hidden away in some method where you can't see them in your test.

I've seen plenty of people use helper methods to initialize variables and such for their tests. This is a very bad idea if any of that information is important to that specific test. Only hide away unimportant details. For instance you might hide away the initialization of your mocked objects, but you would keep the player's points you will be Asserting the value of front and center. If values are being initialized in a non-test method you should be able to change those tests safely without causing problems.

Treat your tests well and they will be there to help you.

Write a Test Before Fixing a Bug

As I've said in previous posts, it is important to write tests for your code. A lot of the time I am talking about when refactoring code or when writing new code. Now I agree that bug fixing could be considered refactoring, but people seem to treat it differently. When fixing bugs they want to go in and quickly make the bug go away. That is a dangerous way to solve things, because it doesn't prevent the bug from returning.

If a bug exists in your system then there are test cases missing from the system. When you fix a bug, even if you do write a test case to handle the bug how do you know you've tested the right thing? If your test is not right it will not prevent the bug from returning. I know of only one way to be fairly confident that a bug is tested well. The test needs to be written before the fix. If it isn't written first you will not know. If you follow the TDD practice of Red, Green, Refactor, the Red lets you know that you've found the bug. Then when you make it green you can have confidence that you've fixed the bug.

RedGreenRefactor

If you had not tested first you don't even know that your test is accurate. How do you know you actually found what is causing the bug? You can't really be sure with any confidence, because all you saw were green tests. Your test couldn't fail. Either the test didn't actually test the bug or because you fixed it. You hope the latter, but it could be the former.

GreenGreenRefactor

This will not work. For other things I can agree with you that you can write code and then test it, but not for bugs. With bugs the test needs to be written first, so there is some confidence that the bug is being tested. Since code already exists the test needs to be in place first. This same practice should be adhered to when doing refactorings of working code as well. The point in that case is also to prevent software regressions caused by the refactoring. Tests help you hold existing functionality, and in the case of bug fixing they help to ensure that the bug has truly been fixed and tested to prevent a return.

Software bugs are like bad musicians. If you don't actively prevent them, they will make a comeback.

Example

As an example of this. We can assume that we have two classes. One of them is called Student and the other is called Course. To represent this example we are going to have some badly written code which is going to cause us to have a few nasty bugs (Badly written code makes for easier examples). From our knowledge  of the domain, we know that students take a few courses at a time, so there is a collection of courses associated with a student.

Say our student has a property called Courses and that property holds the collection.

public class Student
{
    public int ID { get; set; }
    public List<Course> Courses { get; set; }
}

Now we say that somewhere we are caching the Student objects based on their IDs. We want to make sure that if the student object is changed that we expire the cache, so we will cache it with a SqlCacheDependency on the database table for the Student object.

Assume we have a "View my courses" page for the student to get information about the courses. For ease, it will obviously grab the student object out of cache and use its collection of courses to display the information if the information is already there.

What bug have we created here?

Well we've now made it so that if any of the courses change this change will not be reflected on the courses page of any student currently in the cache. There are literally probably a dozen ways of fixing this bug. Plenty of ways we could have prevented it, but then we wouldn't have this nice example now would we?

All I am saying is that some unit tests and integration tests be written for these before we fix the problem. This lets us be sure that we've fixed the problem correctly.

The first test I would write is one that loads a student object (making sure that is gets cached) and then separately loads one of the courses the student is in and alters that course. I would then make sure that the change to the course succeeded and then I would get the student again, (it would come out of cache this time) and I would verify that it had the change I made to the course. I would expect that the first time I run it that the test will fail. If it doesn't fail, or fails for a reason other than what I expected, I need to fix it so it fails the way I expect.

Once it is failing correctly I can adjust the code to make it work correctly. I would call this an issue violating the single responsibility principle, because the Student object in my opinion shouldn't be holding a local copy of the Courses. If it doesn't have that then it will not be able to cache it. I think that property should just be a getter calling through to some Course-related class which can cache it if it wants to. Even though these are obviously domain objects, we should try to keep them separated a little bit better, because keeping them too close can cause some annoying bugs.

As always, have a great day, and keep testing your code.

One Reason to Test Before Creating a Method

Most people who know about Test Driven Development have heard the phrase, "Red, Green, Refactor". When it comes to actual implementation of this technique there seems to be a bit of a disagreement. By following the rules of RGR we all agree that we start by writing a failing test (Red), we write the code to make the test pass (Green), and then we make the code better and remove duplication (Refactor). The point of contention I hear about most often is in the Red stage. Some people say to write the failing test before writing any code. Some people say that you can make a skeleton of the code and write the test for that.

In practice I tend to agree with the people that make the skeleton code first. I really just don't like having the compiler error be how my test fails. What I do instead is create the code I am going to test and have it throw a NotImplementedException. This lets me make sure the test is failing so I am sure to flesh out the code.

Now I can certainly see reasons to do both. That is just what I prefer. One interesting problem which can arise from doing my method is the following. Say that I am going to create a new method on a class, so I create the method and write the failing test. Perhaps this is a non-tested project I am working on, so only the new stuff is tested. I write my code and everything passes now. But I've created a new bug. How?

I am kind of cheating here because there is a compiler warning. Since not everyone treats compiler warnings as errors it is certainly possible to have missed this problem. Here is some example code including an extra base class I didn't mention yet.

class Program
{
    static void Main(string[] args)
    {
        Foo myFoo = new Foo();

        myFoo.Bar();
    }
}

internal class BaseFoo
{
    public void Bar()
    {
        Console.WriteLine("Base Bar!!");
    }
}

internal class Foo : BaseFoo
{
    public void Bar()
    {
        Console.WriteLine("Bar!!");
    }
}

So now if I create a method called Bar without realizing there was already one on the parent class I will be hiding the parent one and breaking the existing logic. Since the old code isn't tested I will not know about it. If I had written a test before the code, I would have noticed something odd when the compiler didn't throw an error.

I think it is an interesting debate. Not very important, but interesting. Perhaps people have some more reasons why it should be one way or the other.

Beginning Unit Testing

Getting started unit testing is a difficult task. I've seen plenty of people learning to unit test and it took some time for me and seems to take some time for everyone before unit testing really clicks. Part of the reason why unit testing is difficult for people to get started with is that the code most developers write is not testable. Yes, not only is it important to test, but it is important for your code to be testable. Most code is so difficult to test that anyone who doesn't know how to unit test will have a great deal of trouble testing anything.

Most testing is difficult because the code you're trying to test has too many dependencies. So we all know that we write code which depends on other code we write. There are a few important dependencies that a lot of people forget about.

Breaking the DateTime Dependency

One seemingly safe piece of code to test is the DateTime class. How is it often used? Well, people use DateTime.Now or DateTime.Today in their code. So what is the big deal? Isn't this easy to test? NO! Testing a method which uses either of those two values is not easy at all. If your application cares about the time of day at all, it is impossible to test it reliably if you're using DateTime.Now.

Two cases for time come into my mind right now: checking for weekends and checking morning, afternoon, and evening. A couple of interesting sites I enjoy change the theme of the site based on the time of day. How could you test that logic? Well, not easily if you're using DateTime directly. To get around this wee need to break the dependency. To do this we need to work with an interface which gives us access to all the logic we used from the DateTime class.

interface ICalendar
{
    DateTime GetCurrentTime();
    DateTime GetCurrentDate();
}

public class Calendar : ICalendar
{
    #region ICalendar Members

    public DateTime GetCurrentTime()
    {
        return DateTime.Now;
    }

    public DateTime GetCurrentDate()
    {
        return DateTime.Today;
    }

    #endregion
}

If you need any more attributes from the DateTime class add the methods for them to the interface and the class.

In order to use these methods in production with our TimeOfDay class, we will need to do a couple of things. As a general rule, it is important to program against an interface. We will start by creating a stub for the class and then testing the stub.

public class TimeOfDay
{
    private ICalendar _calendar;
    public TimeOfDay() : this(new Calendar())
    {
    }

    public TimeOfDay(ICalendar calendar)
    {
        _calendar = calendar;
    }

    public bool IsMorning()
    {
        throw new NotImplementedException();
    }

    public bool IsEvening()
    {
        throw new NotImplementedException();
    }
}

Now we go and write a couple of test methods which we want to have fail since we haven't implemented our methods yet. Then once we've got the tests in place we can fill in the code and have confirmation that we have written it correctly.

[TestClass]
public class TimeOfDayTester
{
    private FakeCalendar _myFakeCalendar;

    public TimeOfDayTester()
    {
        _myFakeCalendar = new FakeCalendar();
    }

    [TestMethod]
    public void OneMinuteBeforeTenAMShouldBeTheMorning()
    {
        _myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 9, 59, 00);
        TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
        Assert.IsTrue(timeOfDay.IsMorning());
    }

    [TestMethod]
    public void NoonShouldNotBeTheMorning()
    {
        _myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 12, 00, 00);
        TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
        Assert.IsFalse(timeOfDay.IsMorning());
    }

    [TestMethod]
    public void EightPMShouldNotBeTheMorning()
    {
        _myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 20, 00, 00);
        TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
        Assert.IsFalse(timeOfDay.IsMorning());
    }

    [TestMethod]
    public void SixPMShouldBeTheEvening()
    {
        _myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 18, 00, 00);
        TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
        Assert.IsTrue(timeOfDay.IsEvening());
    }

    [TestMethod]
    public void NoonShouldNotBeTheEvening()
    {
        _myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 12, 00, 00);
        TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
        Assert.IsFalse(timeOfDay.IsEvening());
    }

    [TestMethod]
    public void EightAMShouldNotBeTheEvening()
    {
        _myFakeCalendar.CurrentTime = new DateTime(2001, 1, 1, 8, 00, 00);
        TimeOfDay timeOfDay = new TimeOfDay(_myFakeCalendar);
        Assert.IsFalse(timeOfDay.IsEvening());
    }
}

Now we can execute the tests and see them fail. This confirms that we haven't made any bad assumptions.

NotImplementedTestFailures

Now we go and write the code which makes the tests pass. Once the tests pass we know that the code works.

public class TimeOfDay
{
    private ICalendar _calendar;
    public TimeOfDay() : this(new Calendar())
    {
    }

    public TimeOfDay(ICalendar calendar)
    {
        _calendar = calendar;
    }

    public bool IsMorning()
    {
        return (_calendar.GetCurrentTime().Hour < 10);
    }

    public bool IsEvening()
    {
        return (_calendar.GetCurrentTime().Hour >= 18);
    }
}

So now when we run our tests again we should see all green passing tests.

PassingTests

If we hadn't kept the DateTime class at arms length we wouldn't have been able to easily test the class. The reason we can't is because we are not able to set the value which will be returned from DateTime.Now. Anytime you use classes which magically give you access to something, they better have an interface. If they do not have an interface then you will need to use a solution like this one to wrap the class inside of another one.

Where Should Test Classes Go?

LegacyCodeBook In Working Effectively With Legacy Code, the author talks about where to place test classes in your applications structure. He mentions that you should place test classes along side production code in the structure of your application. Why? Well he says that it is good because it helps you navigate between the test classes and the production code easily.

I somewhat agree with him when he says this, because a lot of time is wasted moving between classes. I admit I am one of the people who tries not to mix too much test and production code. I like to keep anything test related at arms length. Why do I do this? Because I believe that everything becomes cleaner and easier to observe when it is separated. I believe there is some reason to keep things aesthetically pleasing, and I certainly believe that keeping them separate will make the system appear a lot less daunting.

Navigating Between Test and Production Code

So I've explained what I like about keeping the two together, but I still haven't made an argument for why I don't need the "navigation" benefits of keeping the two together. The way I handle this is through superior add-ins to my IDE. I use Resharper to give me better navigation. Lately I've become quite fond of this application. If nothing else just for the ability to navigate to classes and files in the solution based on the name alone.

GoToType1

This is incredibly powerful, and it is a quick keyboard shortcut away. It lets you navigate quickly and easily. I like it because it lets me organize how I want to, and I don't need to worry about moving from one assembly to another even. I keep my unit tests in a separate project from any production code. Since I can still navigate quickly, I get all the benefits of both methods.

I think there are a lot of great suggestions people can make for how to code, but at the end of the day you need to make your own choice. Consider people's suggestions, understand why they make them, and certainly adjust them to your own uses.

My opinion is that test classes should go in a separate location. It keeps the production app less cluttered. The application will not deploy test code. If they're separated there will never be any confusion. It would just be terrible if you had a class that actually needed to have the word "test" in the name.