Brendan Enrick

Daily Software Development

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.

Organizing Software Projects

Managing and structuring software applications is a complicated topic. Many different ways of structuring applications exist, and there are merits to several methods of organization. In this post, I am going to roughly describe a method of organizing a software application to which I am somewhat partial.

One of the most important aspects of a well-organized project in my opinion, is the ability for a new developer on a project to be able to sit down and have a working solution as soon as they get the latest version of the application from the source control repository. Not only should that person be able to have a working solution, but that working copy should assist the developer in setting up the local environment. The solution should also be in a state which allows all of the project's tests to run without the user having to jump through a bunch of hoops.

Being able to sit down and start working immediately is very powerful. We wouldn't be able to achieve this without first having things packaged and tested nice. We are allowing anyone to figure out how things work based on the logic standardized and explained by our tests. The developer is now able to make meaningful, useful changes to the project right off the bat by making modifications and testing them. As long as they're not breaking existing tests, they can have some confidence that they're meaningfully contributing to the project.

Combined with continuous integration we are able to know that the project is in a tested, working state, and when we check out the source for the project, that it should work correctly already. There are a few pieces which must be in place in order for this to work. We need to make sure that the class libraries we're depending on are included in relative paths in the source control repository, so we don't have to worry about whether or not they are installed on the developer's machine. We also need to make sure that we have the project sufficiently well tested. Build scripts are also vital in allowing someone to sit down and start working immediately.

When deciding what tools to use for testing and for your build scripts, it is important to decide which tools you can safely assume will be on the developer's machine. As far as I know, you can't package MSTest or MSBuild along with your project. If everyone who uses this code will have these, then it is perfectly acceptable to depend on them. If that is not the case, I would recommend using NUnit and NAnt. These tools are very similar and are easy to use. Their integration with Visual Studio is not as nice, but they are easier to have dependencies on.

The trunk looks somewhat similar to this.

trunk-explorer

See that at this first level of the application, we have very little clutter. Things should be kept neat and tidy here, so that people just checking this code out aren't overwhelmed by anything before opening this. The lib folder contains class libraries that the project has dependencies on as well as the tools for building. This includes things like NUnit. By keeping it out here we are starting off having the opinion that these should be kept at arms length the whole time while working with the project. The less our dependencies integrate with our source the better off we are.

src-explorer

At this level inside the src folder, it is important to see that we still haven't shown any of our clutter. We of course get a lot more cluttered once we see the source code. I don't mean that the code is messy, but seeing a dozen files is a lot messier than a handful of folders and a solution. At this level someone can open up the solution and see the project from within Visual Studio already knowing that the solution works. How do we know it works? We ran the BuildAndTest file and it made sure that the project built and that all of the tests passed.

That little addition of having the ability to build and test the project is so valuable, because in a moment anyone can know if the project is working. We get quick feedback without even having to load visual studio. We don't have to search for the files among others; they're right there on their own.

Good luck, good organizing, good testing, good night.

And now an opportunity to promote Jeffrey Palermo's class. If you are interested in learning about Agile software practices, I recommend taking the Agile Bootcamp class offered by Headspring Systems. I learned a great deal from that class, and a lot of the practices I currently use are adaptations of what I learned. It isn't a class that tells you exactly how to do things, it shows you a way of doing things that works, which you will be able to take and adapt to how you're already working.

Silverlight Attached Properties

One cool feature of XAML is the concept of an attached property. These properties are a way of extending the properties of an element in XAML. By this I don't mean that you can add any arbitrary extra property to an element. What I mean is that child elements have certain properties from their parents attached to them. This is often used as a way of allowing a child element to interact with a parent.

A couple of examples of what I mean can be found in the DockPanel and the Canvas elements. Some attached properties you will find from the Canvas element are Canvas.Top, Canvas.Left, and Canvas.ZOrder. These three let you control the location of the child element within the canvas. A DockPanel element gives DockPanel.Dock, because it is important to know where on the DockPanel your child element is docked.

You have probably noticed by now the naming of these attached properties. They are named in the following way.

ElementName.PropertyName

Here are some examples of how to use these.

<DockPanel>
  <Button DockPanel.Dock="Left"/>
</DockPanel>

<Canvas>
  <Ellipse Width="100" Height="100" Fill="Black"
    Canvas.Left="25" Canvas.Top="25" />
</Canvas>

Notice I've docked the button to the left of the DockPanel and the Eliipse has been positioned away from the left and away from the top of the canvas.

It would be a nightmare to try to control positioning of elements inside of the canvas anywhere but on the specific element, and the attached properties allow this to happen. I think they are quote cool.

Windows Home Server Becoming Available on MSDN

windows-home-server Earlier today I went looking to see if MSDN included Windows Home Server. Well, it doesn't include it. I looked in the "servers" section, the "operating systems" section, and when that failed I asked Google. I read the Official MSDN Subscriptions Blog, which contained a post about Windows Home Sever. It seems that including Windows Home Server was considered and rejected. Thanks to the post on that blog, a lot of feedback was received requesting its inclusion as well as information about why it was not included. Thanks to an update on that post, I know that a year ago they said they would be reconsidering it based on the feedback.

I still don't see it as an available download, but luckily there has been follow up information on the issue. Philip Churchill posted about WHS Coming to MSDN a couple of months ago. Now, I sit around waiting for Microsoft to deliver this awesome product to their faithful MSDN crew. I just used one recently, and it is very easy and nice to use. I now see what all of the hype has been about. For once I think the hype was not exaggerating the product. At least not much.

I look forward to the release of Windows Home Server on MSDN. I hope you do also, since I will most certainly write about it once they release it.