Monday, November 28, 2005

Unit Test Guidelines

Tests live under many names. And, many tests masquerade as unit tests.

Unit testing is defined as:
... a procedure used to verify that a particular module of source code is working properly. The idea about unit tests is to write test cases for all functions and methods so that whenever a change causes a regression, it can be quickly identified and fixed. Ideally, each test case is separate from the others ... [Wikipedia]

There are existing practices that I consider to be good guidelines concerning unit testing.

  • William Caputo - Do Not Cross Boundaries. The central idea is to decouple the code from the resources. An added benefit is the reduced running time of the tests. The faster the tests are, the more often they are run.
  • Dave Astels - One Assertion Per Test. While the idea is controversial it's also very thought provoking. If you follow this rule your tests become simple, expressive, and elegant. I don't follow this rule 100% of the time; however, I do believe it's a great guideline.

I follow another guideline that I haven't seen documented anywhere.
Only one concrete class (with behavior) should be used per test.
The central reason for testing concrete classes individually is to promote durable tests. When several concrete classes are used in one test the test becomes brittle. Making a change to any of the coupled concrete classes can cause cascading test failures.

Both mocks and stubs can be used in place of concrete classes where necessary while testing an individual class. If you find your hierarchy too complicated to use mocks or stubs this is probably a sign that you need a simpler and less coupled hierarchy. Using Object Mother is a common alternative to refactoring to a better hierarchy. If you find yourself reaching for Object Mother, take the time to refactor instead.

Sunday, November 27, 2005

What's in your build?

A basic build generally consists of clean, compile, and test. However, you can (and should) add more or tweak the build to make life easier and increase the quality of the code you produce. Most people _hate_ working on the build. Build languages are usually painful to work with and optimizing the build isn't very exciting. However, you should be running the build several times a day so each optimization can save you a lot of time over the life of the project.

  • Separate Tests - Create unit tests that test specific responsibilities of individual classes. Create functional tests that test classes working together to achieve a larger goal.
  • Database Generation - Use database scripts to generate the database during the build. Optimize the process by only dropping and adding tables, views, etc when the script(s) change. However, clear and reload the sample data on each build to ensure functional tests are hitting consistent data each build.
  • Simian - Use Simian to ensure that duplicate code is not slipping into your code base.
  • Code Coverage - I admit it, Code Coverage can be misleading. However, managers and business sponsors love charts with reassuring numbers. Additionally, if the team pays little attention to the code coverage number an interesting thing happens. No one attempts to trick the code coverage numbers and they become useful. When the numbers dip below tolerance the tech lead can use the warning to suggest to the team that more focus be given to testing. Note: The tech lead should never mention that the code coverage tool tipped him off or the team may start writing worthless tests that satisfy the code coverage tool, thus rendering it useless.
    For .net use NCover (the version that fits your needs) or Clover.net, for Java I believe Clover is the most popular
  • Modification Compilation - Use a build language that can detect modification dates. Components of your application only need to be recompiled when changes are made to the source files.

There are other tools such as CheckStyle and FXCop that are supposed to be helpful. In theory they sound great; however, I've never used either so I didn't include either. Please let me know if you have any suggestions or optimizations I've missed.

Friday, November 18, 2005

Adding NanoContainer

After you have already decided to Add PicoContainer you can go a step further and use NanoContainer. NanoContainer is a complement to the PicoContainer project, providing it with additional functionality. One aspect of NanoContainer is the ability to mark your classes with an attribute that PicoContainer can use to register components.

Using NanoContainer attributes is very easy. Each of my classes need to be registered with default options (Constructor Injection, Caching); therefore, all I need to do is add the [RegisterWithContainer] attribute to each class. I add this attribute to all the classes I want registered; however, I'll only show PresenterFactory.
[RegisterWithContainer]
public class PresenterFactory
{
public Hashtable presenterHash = new Hashtable();

public PresenterFactory(IPresenter[] presenters)
{
for (int i = 0; i < presenters.Length; i++)
{
this.presenterHash[presenters[i].View.GetType()] = presenters[i];
}
}

public IView Find(Type type)
{
IPresenter presenter = (IPresenter) presenterHash[type];
presenter.Push();
return presenter.View;
}
}

After adding the [RegisterWithComponent] attribute I change the EntryPoint class implementation to use the AttributeBasedContainerBuilderFacade. The BuilderFacade will create a new instance of IMutablePicoContainer that I can use to register my UserData instance. I can also continue to use the container to get an instance of the MainPresenter.
public class EntryPoint
{
[STAThread]
static void Main()
{
ContainerBuilderFacade containerBuilderFacade = new AttributeBasedContainerBuilderFacade();
IMutablePicoContainer container = containerBuilderFacade.Build(new string[] {"SampleSmartClient.UI.dll"});
container.RegisterComponentInstance(createUser());
MainPresenter presenter = (MainPresenter) container.GetComponentInstance(typeof(MainPresenter));
Application.Run(presenter.MainForm);
}

private static UserData createUser()
{
UserData user = new UserData();
user.Name = "John Doe";
user.JobTitle = "Rockstar";
user.PhoneNumber = "212-555-1212";
user.Password = "password";
return user;
}
}


As I previously noted, using NanoContainer Attributes does add a dependency to NanoContainer. Some people are very against this idea. Personally, it seems like another case of concern over less dependency for less dependencies sake. Adding a dependency to NanoContainer should cause you no pain, but it will clean up your code. The achieved clarity in code is worth the added dependency.

Adding PicoContainer

I recently blogged about Rich Client Development in a 4 part series that led to a small reference implementation. It is immature, but it's in perfect condition to demonstrate the value of PicoContainer.

The current implementation of the EntryPoint class looks like this:
public class EntryPoint
{
[STAThread]
static void Main()
{
MainForm mainForm = new MainForm();
UserData userData = createUser();
new MainPresenter(mainForm, createPresenterFactory(userData));
Application.Run(mainForm);
}

private static UserData createUser()
{
UserData user = new UserData();
user.Name = "John Doe";
user.JobTitle = "Rockstar";
user.PhoneNumber = "212-555-1212";
user.Password = "password";
return user;
}

private static PresenterFactory createPresenterFactory(UserData user)
{
return new PresenterFactory(getPresenters(user));
}

private static IPresenter[] getPresenters(UserData user)
{
return new IPresenter[] { getReadPresenter(user), getUpdatePresenter(user) };
}

private static IPresenter getReadPresenter(UserData user)
{
ReadView view = new ReadView();
return new ReadPresenter(view, user);
}

private static IPresenter getUpdatePresenter(UserData user)
{
UpdateView view = new UpdateView();
return new UpdatePresenter(view, user);
}
}

While this is clean, it's a bit more verbose than necessary. A simpler solution is to register each type with PicoContainer and allow Pico to resolve the dependencies. The only exception is that I would like to populate a UserData instance that will be used as a constructor argument to many other classes. Pico allows me to do this using RegisterComponentInstance. Converting my EntryPoint class to take advantage of PicoContainer causes the implementation to look like this:
public class EntryPoint
{
[STAThread]
static void Main()
{
DefaultPicoContainer container = new DefaultPicoContainer();
container.RegisterComponentInstance(createUser());
container.RegisterComponentImplementation(typeof(PresenterFactory));
container.RegisterComponentImplementation(typeof(MainPresenter));
container.RegisterComponentImplementation(typeof(MainForm));
container.RegisterComponentImplementation(typeof(ReadPresenter));
container.RegisterComponentImplementation(typeof(ReadView));
container.RegisterComponentImplementation(typeof(UpdatePresenter));
container.RegisterComponentImplementation(typeof(UpdateView));
MainPresenter presenter = (MainPresenter) container.GetComponentInstance(typeof(MainPresenter));
Application.Run(presenter.MainForm);
}

private static UserData createUser()
{
UserData user = new UserData();
user.Name = "John Doe";
user.JobTitle = "Rockstar";
user.PhoneNumber = "212-555-1212";
user.Password = "password";
return user;
}
}

This implementation is shorter and arguably easier to understand. Notice PicoContainer creates instance of the dependent objects I need including an array of IPresenters that are used as a constructor argument to the PresenterFactory. If you design your class as Good Citizens and prefer Constructor Injection, adding PicoContainer should be easy and very worthwhile.

MVP and Dialog

I recently received a request to show how Model View Presenter and a modal dialog could work together. I'm going to use the existing rich* client example I've been working with lately. For demonstration purposes we will assume that the UserData class has a password property that contains a user's password. When a user updates their information they will be prompted to enter their password. Successful authentication updates their information and navigates the user to the read only view. Unsuccessful authentication does nothing, but clicking "Cancel" will close the dialog without saving info and without navigating away from the update view.

The modification is to add a password to the existing UserData instance.
public class EntryPoint
{
private static UserData createUser()
{
UserData user = new UserData();
user.Name = "John Doe";
user.JobTitle = "Rockstar";
user.PhoneNumber = "212-555-1212";
user.Password = "password";
return user;
}

...
}

The only change to the UpdateView is to remove the NavigationDispatcher.RaiseNavigate method call from the saveButton click handler. We'll now handle navigation in the presenter (perhaps we should have moved it when we introduced the NavigationDispatcher anyway).

The SaveUserDialog is a Windows Form that allows a user to enter a password and save, or cancel and do not save.

SaveUserDialog exposes it's PasswordTextBox as a public field. When a user clicks the "Save" button SaveUserDialog raises the RequestAuthorization event. Clicking "Cancel" just closes the form.
public class SaveUserDialog : Form
{
private Label label1;
public TextBox PasswordTextBox;
private Button saveButton;
private Button cancelButton;
public event UserAction RequestAuthorization;
private Container components = null;

public SaveUserDialog()
{
InitializeComponent();
}

... deleted generated code...

private void saveButton_Click(object sender, EventArgs e)
{
RequestAuthorization();
}

private void cancelButton_Click(object sender, System.EventArgs e)
{
this.Close();
}
}

The presenter for the SaveUserDialog has the responsibility of verifying the password matches and then setting the dialog.DialogResult = DialogResult.Yes.
public class SaveUserPresenter
{
private readonly SaveUserDialog dialog;
private readonly string password;

public SaveUserPresenter(SaveUserDialog dialog, string password)
{
this.dialog = dialog;
this.password = password;
dialog.RequestAuthorization+=new UserAction(AuthorizeSave);
}

private void AuthorizeSave()
{
if (dialog.PasswordTextBox.Text==password)
{
dialog.DialogResult=DialogResult.Yes;
dialog.Close();
}
}
}

I considered passing the entire UserData object to the SaveUserPresenter; however, it seemed easier to keep this presenter as thin as possible and keep the save functionality in the UpdatePresenter. If more functionality were required I wouldn't hesitate to pass in more objects and give more responsibility to the SaveUserPresenter.

All of these changes and additions come together in the UpdatePresenter. The UpdatePresenter is now responsible for creating and showing the SaveUserDialog. Additionally, the UserData instance should only be updated if the SaveUserDialog returns DialogResult.Yes. Lastly, the UpdatePresenter is also responsible for calling NavigationDispatcher.RaiseNavigate if DialogResult.Yes is set.
public class UpdatePresenter : IPresenter
{
private readonly UpdateView view;
private readonly UserData user;

public UpdatePresenter(UpdateView view, UserData user)
{
this.view = view;
this.user = user;
view.Save+=new UserAction(updateUser);
Push();
}

public IView View
{
get { return view; }
}

public void Push()
{
view.NameTextBox.Text = user.Name;
view.JobTextBox.Text = user.JobTitle;
view.PhoneTextBox.Text = user.PhoneNumber;
}

private void updateUser()
{
SaveUserDialog dialog = new SaveUserDialog();
new SaveUserPresenter(dialog, user.Password);
if (dialog.ShowDialog()==DialogResult.Yes)
{
user.Name = view.NameTextBox.Text;
user.JobTitle = view.JobTextBox.Text;
user.PhoneNumber = view.PhoneTextBox.Text;
NavigationDispatcher.RaiseNavigate(typeof(ReadView));
}
}
}

If my application contained several modal dialogs I would also look at possibly moving the creation into a factory similar to the PresenterFactory. Each presenter could take the DialogFactory as a constructor argument allowing for easy access.

For testing purposes I would create a IDialog interface that contained the DialogResult property. Each Dialog would obviously implement the IDialog interface and the dialog presenters would take an IDialog as a constructor argument instead of the concrete class. This would allow me to easily mock the dialog when testing the SaveUserPresenter.

* thanks to Matt Deiters for pointing out that, contrary to popular belief, smart and rich are different. (luckily, Matt is both)