Sunday, January 13, 2008
#
I recently finished 6 weeks of coding for a client, and it was heaven! I actually got a chance to code every day, for 6 solid weeks. It was a chance for me to learn C# 3.0, and a chance to work on testing things that are hard to test. It was great!
Out of the work, came several interesting observations and coding techniques, all rooted in C# 3.0. Since no one at work has any experience with these new idioms I "invented", "discovered", or just "copied", I'd love to get some reader feedback. I'll start with this one trick I tried, and follow on with more as the mood strikes me over time.
Trick 1: Using extension methods and a marker interface in place of implementation inheritance
I had an instance of code duplication in two parallel hierarchies of classes, and I wanted to find a way to share the code. One option would be to use inheritance, factoring out another base class above BaseResponse and BaseRequest. This is where methods common to requests and responses could both live. Using inheritance as a way to reuse code in a single inheritance language is a pretty heavyweight thing to do. I'd rather find a way to use delegation, since that preserves the SRP in my class hierarchy. Instead, I decided to try an extension method, and just use that method where I needed it. To avoid polluting Object with unnecessary methods, however, I came up with the idea of using a marker interface on the classes I wanted to have these extension methods, limiting the scope where these extra methods were visible. (No idea if anyone else has done this yet or not)
For each request and response class, in the two parallel hierarchies, my client requirements made it necessary to add an XmlRoot attribute to tell the XmlSerializer that this object was the root of an XML document and to specify the runtime name of this element. To let me get the runtime name of each request and response object, for auditing and logging purposes, both hierarchies had a CommandName property, containing the exact same code. This was the code in question that I was trying to share.
As a simple exercise, I created an extension method to deal with this:
internal static class SssMessageExtensionMethods
{
public static string GetCommandNameFromXmlRootAttribute(this object message)
{
object[] attributes = message.GetType().GetCustomAttributes(typeof(XmlRootAttribute), true);
if (attributes.Length == 0) return message.GetType().Name;
XmlRootAttribute xmlRootAttribute = attributes[0] as XmlRootAttribute;
return xmlRootAttribute.ElementName;
}
}
This solution worked just fine, and the code ran correctly, but I still wasn't happy with my solution. The problem I was sensing was that I was adding yet another extension method to Object, and Object's neighborhood was already pretty crowded with all the Linq methods in there. I wanted my extension methods to show up only on those classes to which I wanted to apply them.
The solution that I came up with was to use a marker interface whose sole purpose is to limit the visibility of the extension methods to classes that I intend to apply them to. In this case, I made BaseRequest and BaseResponse each implement IMessageMarker, an interface with no methods. And I changed the extension method to be:
internal static class SssMessageExtensionMethods
{
public static string GetCommandNameFromXmlRootAttribute(this ISssMessageMarker message)
{
object[] attributes = message.GetType().GetCustomAttributes(typeof(XmlRootAttribute), true);
if (attributes.Length == 0) return message.GetType().Name;
XmlRootAttribute xmlRootAttribute = attributes[0] as XmlRootAttribute;
return xmlRootAttribute.ElementName;
}
}
Now I have the same extension method defined, but it only appears on those classes that implement the marker.
What do you think of this technique? In a more powerful language, like Ruby or C++ (ducking and running for cover!), this kind of trickery wouldn't be needed. But C# can only get you so far, so I felt this was a good tradeoff between adding the methods for needed functionality and making the most minimal change in my classes to hide these methods so that only those places that needed them could see them.
-- bab
Saturday, November 17, 2007
#
I was trying to install the Application Block Software Factory, part of Enterprise Library 3.1, the other day, and I ran into a problem. During the installation, I got a failure stating that the necessary installer types could not be found in "c:\program files\Microsoft Visual Studio 8\common7\ide\Microsoft.Practices.EnterpriseLibrary.BlockFactoryInstaller.dll". I was instructed to see the LoaderExceptions property of the exception for details.
Huh? How in the world was I supposed to see this property of an exception that I didn't even have access to?????
Powershell to the rescue
Hmmm, I thought. Based on a previous blog posting, I remember that I found a way to load an assembly from a file, and I knew that I could inspect the types in an assembly once it was loaded. Maybe I could follow this process to learn something about what was happening.
So, I fired up powershell, and typed in the following command (note that I'm at home and not at work in front of the PC where I did this. The paths are as close as I can remember...)
$assembly = [System.Reflection.Assembly]::LoadFile("c:\program files\Microsoft Visual Studio 8\common7\ide\Microsoft.Practices.EnterpriseLibrary.BlockFactoryInstaller.dll")
Once I had the assembly loaded like this, I used its GetTypes() method to inspect the types in the assembly, and that's when I got the same exception as before.
After a little investigation, I came across the $Error special variable, which seems to hold an array of the last exceptions through during powershell execution. I was able to get to the exact exception I saw at the command line through this variable by typing $Error[0].
I investigated further by using the get-member cmdlet, as
$Error[0] | get-member
which told me that the object returned from $Error[0] had an Exception property on it. I followed on a bit, and looked at the members of the exception I could get to using $Error[0].Exception. Here, it turned out, there was a property called LoaderExceptions, which was the exact property that I had been instructed to see by the error message.
Looking at that property as:
$Error[0].Exception.LoaderException[0]
gave me the exact right answer. It was looking for Microsoft.Practices.Recipes.dll, an assembly loaded by GAX, but it couldn't find it. I searched for that assembly, and I did eventually find it, but it was installed beneath Orcas, not Whidbey, both of which I had installed on my machine.
The solution
So, to make a long story short, I reinstalled GAX, this time installing it for VS.Net 2005, and all was well. I was able to install the Enterprise Library in its entirety, and I was able to proceed.
But, without the ability of powershell to let me iteratively understand what was happening, and explore the objects involved, I don't know how I would have otherwise solved this problem.
-- bab
I had what was probably an obvious insight the other day while I was working on my project alone. I'm a team of one, which kind of gets in the way when it comes to pairing. This, unfortunately, has an effect on my final code.
Good pairs are adversarial
When you find yourself pairing with someone really good, it can almost feel adversarial. What I mean by that is that you can get into a rhythm where one person writes a test, intending to lead his partner down the road of writing a particular piece of code. His partner, however, can write something entirely different that still causes the test to pass.
This back and forth dance between tester and implementer forms the basis of good micro pairing sessions. In these sessions the tester/driver intends to lead the implementer down a particular path, but the implementer has the option of following another way, forcing the test writer to write another test, trying to drive the implementer down the intended path, and so on.
This leads to particularly good code, as the code that is written is usually the least code possible to implement the functionality, and the tests that are written thoroughly cover the functionality that was intended. It's really cool to watch this work.
If you're a pair of one...
If you happen to be working by yourself, it is very difficult to simulate this tension between test authoring and application implementation. At least, from my point of view, what happens is that I do write the code I want to test to lead me to, regardless of whether or not there is a simpler way to get the test to pass. I think it is natural to do this, since you're trying to play both sides of the partnership.
I think code I write without a pair is inferior to code I create with a partner, for this exact reason. We didn't fight over the minimal implementation, which leads to still good code, but not the glory that is fully paired/TDD code.
There ain't nothing better.
-- bab
Monday, November 05, 2007
#
Update — Craig Buchek pointed out something about one of my tests that he didn’t like. My test entitled PresortedBookListWithSomeBooksInCorrectGenreOnlyReturnsBooksInCorrectGenre made an assumption about data ordering that was stronger than was necessary for the intent of the test. I didn’t need to show that the elements came out of the filtered list in sorted order for that test — I only needed to show that the elements were present in the filtered list. I’ve updated the area around that test with new content explaining the interesting lesson that Craig taught me. Thanks to Craig and all the participants on the XPSTL list.
OK, time for story number 2 —
I want to see just those books that are in a specific genre, sorted by title, so that I can survey which books I have on particular topics.
Fortunately for us, this turns out to be trivial in .Net 2.0 (Sorry, Java guys!).
First case — test for 0
As I said in the previous episode, when faced with the challenge of implementing a story that involves multiple results, follow the rule of 0, 1, many. So here is my test for getting no books back when there are no books in my genre:
[Test]
public void NoBooksReturnedWhenFilteringEmptyListOfBooksForGenre()
{
BookListManager manager = new BookListManager();
List<Book> filteredBookList = manager.GetBooksInGenre("Genre");
Assert.IsEmpty(filteredBookList);
}
I puzzled a bit about the name of our new member funcction, GetBooksInGenre. Should it be FilterBooksByGenre, GetAllBooksInGenre, or any one of several other candidates? I played with each of them, trying them out for size, thinking about whether or not I liked the way the API felt. The fact that I was thinking about the API now, before I implemented the functionality, is actually pretty important. This is one of the key differences in Test Driven Development versus Test-at-the-same-time Development or Test After Development. In the latter two kinds of development, you write the code, putting a stake in the ground representing a potentially significant amount of work. It is only after the code is written that you start exercising the interface that you’ve written. In the first way, using Test Driven Development, you play with the interface first, without regard to how the code will be written, and have the opportunity to get things as best as you can now, before that stake gets planted.
So I finally settled on the API I show in the test. Let’s write enough code to make that test compile but fail:
public List<Book> GetBooksInGenre(string genre)
{
return null;
}
and the final code:
public List<Book> GetBooksInGenre(string genre)
{
return bookList;
}
Again, remember to watch the test fail to make sure that the test can fail, and that your code is making it pass.
Second case — test for 1
Next test is to create a list with one book in it, and that book should have the correct genre being searched for, and filter for that genre:
[Test]
public void SingleBookReturnedWhenFilteringListWithOneBookInCorrectGenre()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("Title", "Genre"));
List<Book> filteredBookList = manager.GetBooksInGenre("Genre");
Assert.AreEqual(1, filteredBookList.Count);
Assert.AreEqual("Title", filteredBookList[0].Title);
Assert.AreEqual("Genre", filteredBookList[0].Genre);
}
OK, so first of all, this test requires a change to our Book class. Previously, Book only had a single argument to its constructor, just a title. Now it needs a genre, which is going to require a change to the Book class to make this test compile. It also needs a Genre property to allow us to test that we get the right book back.
If we start off by changing the constructor for Book directly, we’ll break other tests. What we need to do is find a way to make this change in such a way that we keep our code working and can slowly change to the new constructor. Being able to do this is a critical part of learning to write code using TDD. Each and every change we make to our code needs to made in as small sized steps as possible. This lets us stay close to working code, adding functionality quickly, and then simplifying things immediately afterwards.
The path I’d take is to ignore this new test for a moment. We wrote it, and the act of writing it informed us that we need a different signature for our constructor. So let’s create that constructor and make sure that everything still works after making that change. Once we finish that, we can go back to this test and implement the functionality it is requiring.
Step one in implementing this refactoring is to create a new constructor that takes the two arguments defined in our newest test. Change the old constructor to call the new constructor, passing in a dummy value for the genre in all cases where the old constructor is being called:
public class Book : IComparable<Book>
{
private readonly string title;
public Book(string title) : this(title, "Unspecified")
{
}
public Book(string title, string genre)
{
this.title = title;
}
public string Title
{
get { return title; }
}
public string Genre
{
get { return null; }
}
public int CompareTo(Book other)
{
return title.CompareTo(other.title);
}
}
I also created a property called Genre to let the new test compile. After making this change, all my tests still pass. It is important to note that I didn’t add anything but the absolute minimum I needed to keep the old tests working.
Do not add functionality while refactoring. Resist, resist, resist. Do not add it now, but remember to add tests to force you to add it later.
Now that we have the two constructors, we can realize that we don’t need to original constructor any more, so we can get rid of it, one call-site at a time. This is important, since we don’t have to make a big-bang change but can change one thing at a time. That’s the sign of a well executed refactoring.
Change one site, re-run tests, ensure things still work. Once you’ve found and changed all call sites, remove the old method, recompile and re-run tests. Done! Now, back to that test…
As of right now, we have the new constructor in place, as well as the empty Genre property. We run the test, the test fails. Now lets implement the code to get this test working, which only consists of adding the code behind the Genre property to the Book:
public class Book : IComparable<Book>
{
private readonly string title;
private readonly string genre;
public Book(string title, string genre)
{
this.title = title;
this.genre = genre;
}
public string Title
{
get { return title; }
}
public string Genre
{
get { return genre; }
}
public int CompareTo(Book other)
{
return title.CompareTo(other.title);
}
}
I guess the case of a filtering a list of a single book wasn’t that interesting after all. Let’s write another test that tries to filter another list containing a single book, but let’s make that book have a genre different than that we’re searching for. Maybe that will cause us to write some code.
[Test]
public void NoBookReturnedWhenFilteringListWithOneBookInDifferentGenre()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("Title", "Good"));
List<Book> filteredBookList = manager.GetBooksInGenre("Bad");
Assert.IsEmpty(filteredBookList);
}
Run this test, it compiles the first time, but it fails. I guess we do get to write some code…
public List<Book> GetBooksInGenre(string genre)
{
return bookList.FindAll(delegate(Book book)
{
return book.Genre == genre;
});
}
This code uses the .Net 2.0 anonymous delegate syntax that allows you to create a delegate in place and pass it as a function into the method you’re calling. What happens in the List.FindAll method is that it takes the delegate and applies it to all the elements in the collection, one at a time. In this case, if the Predicate delegate passed in executes and returns true, then the code inside the FindAll method adds the element into a new collection. Once the iteration is finished, the new list is returned to the caller.
The powerful part about doing this is that the new delegate has access to all the state that existed at the point at which it was defined. In other words, even though the delegate we’re defining is being passed as a parameter to the FindAll method and will be invoked later, in a completely different context, it still has access to the methods, members, parameters, and local variables that were in existence at the place where the delegate was defined, which is in our GetBooksInGenre method. Pretty cool, eh? It is an example of how you can create and use closures in .Net.
A bit of test refactoring before we carry on
As Book is growing larger than a single property, we’re going to find ourselves inspecting its list of properties in our tests over and over. When faced with this, I tend to create an Equals method for the object I’m manipulating in my tests. This lets me directly compare the objects in a single Assert.AreEquals. Since the Equals method is code, however, I have to write tests for it, and it usually takes several tests. Here is the code for Book.Equals:
public override bool Equals(object obj)
{
Book other = obj as Book;
if(other == null) return false;
return title == other.title &&
genre == other.genre;
}
and the completed tests for it, in the BookFixture (obviously):
[Test]
public void TwoBooksWithSameGenreAndTitleAreEqual()
{
Book first = new Book("Title", "Genre");
Book second = new Book("Title", "Genre");
Assert.AreEqual(first, second);
}
[Test]
public void DifferentTitlesMakeBooksNotEqual()
{
Book first = new Book("A", "Genre");
Book second = new Book("B", "Genre");
Assert.AreNotEqual(first, second);
}
[Test]
public void DifferentGenresMakeBooksNotEqual()
{
Book first = new Book("Title", "A");
Book second = new Book("Title", "B");
Assert.AreNotEqual(first, second);
}
[Test]
public void NullObjectToCompareToCausesObjectsToBeUnequal()
{
Assert.IsFalse(new Book("", "").Equals(null));
}
[Test]
public void WrongKindOfObjectPassedToEqualsCausesObjectsToBeUnequal()
{
Assert.AreNotEqual(new Book("", ""), "");
}
I personally find an Equals method difficult to implement test first. In my standard working model, I would like to slowly build up the complete set of functionality needed to make something work. I don’t know how to do this with Equals. The problem is that it is difficult to incrementally add behavior to an Equals method and keep a set of growing tests working for it.
For example, I could have defined a test called BooksWithSameTitleCompareEqual, something like this:
[Test]
public void BooksWithSameTitleCompareEqual()
{
Book first = new Book("A", "");
Book second = new Book("A", "");
Assert.AreEqual(first, second);
}
This would lead to a trivial implementation of my Equals method that just compared the titles to see if the objects were equal. Next, I’d add a test comparing the genre of books, but it would have to be crafted in such a way that the titles would be the same as well. And, in the previous test, I would have to have created the test data in such a way that the test wouldn’t break as I added code to compare the genre. My second test would have looked like this:
[Test]
public void BooksWithSameGenreAndTitleCompareEqual()
{
Book first = new Book("A", "G");
Book second = new Book("A", "G");
Assert.AreEqual(first, second);
}
Note that the test has to have the intent of proving that not just the genres are equal, but that all fields we’ve written tests for up to this point are equal. So if we had 5 fields in our class, we’d have to have 5 tests, each growing by one field each time, but still having all other fields “equal” in some way, like the empty genres in my first test. This all feels very contrived and pedantic to me. What I usually do is to write a single test with all fields being equal, and write the positive test case for equality in one fell swoop. The exception to this is when calculating equality is more complex than just comparing fields. If there are loop comparisons involved or something, I will write individual tests for that.
Once this is finished, however, I do tend to write negative test cases for each, individual field, to ensure I haven’t missed something, and tests for passing null and passing the wrong kinds of objects.
That gives me 3 + n tests to write the Equals method for any class, at a minimum, where “n” is the number of fields a class has. When you’re fairly trivial Equals method is only about 5 lines long, and you’ve spent 15 minutes writing all those tests for it, you have to start thinking whether or not it was worth it. Well, my answer is that it is worth it, if you’re writing your Equals method by hand.
I prefer to let my tool generate it for me, in which case I don’t write any tests for it :)
Third case — multiple books
OK, so we’re finally at the point of handling multiple books at a time in our filtering. To get the multi case working, I think I see two separate steps. The first step is to implement filtering across multiple books, while the second step is to make sure that the filtered list is sorted by title. We should break this down into two separate tests.
In the first test, we’re going to check that we’re filtering correctly. In this test, we need to prove that we can filter the list for books having the correct genre. We are not concerned with the ordering of the books here, so we’ll just confirm that the right books are contained in the filtered list (this is the change from Craig). Here it is:
[Test]
public void PresortedBookListWithSomeBooksInCorrectGenreOnlyReturnsBooksInCorrectGenre()
{
BookListManager manager = new BookListManager();
Book firstMatchingBook = new Book("A", "G1");
Book secondMatchingBook = new Book("C", "G1");
Book nonMatchingBook = new Book("B", "G2");
manager.Add(firstMatchingBook);
manager.Add(nonMatchingBook);
manager.Add(secondMatchingBook);
List<Book> filteredBookList = manager.GetBooksInGenre("G1");
Assert.AreEqual(2, filteredBookList.Count);
Assert.Contains(firstMatchingBook, filteredBookList);
Assert.Contains(secondMatchingBook, filteredBookList);
}
The trick I just learned in writing this test is that you have to be conscious of making the assertions in the test match the intent of the test as described in the name. In this case, we are intending to prove that we can filter the list, so our assertions should support this functionality exactly. They should be strong enough to confirm that this behavior is actually happening, but not so strong that they assert behavior that hasn’t been written yet. In our case, that means assertions about filtering, but none about sorting. This is why I’m using Assert.Contains in that test.
While this sounds like a tremendously good plan, unfortunately this test passed the first time I ran it. I understand why it happened — the List.FindAll(Predicate) method I called finds all elements that satisfy the predicate when called. It was the simplest way to get that particular test working, and I got the looping logic for free.
Now for the test of making sure that the filtered list I get is sorted:
[Test]
public void UnsortedBookListWithSomeBooksInCorrectGenreOnlyReturnsBooksInCorrectGenre()
{
BookListManager manager = new BookListManager();
Book firstMatchingBook = new Book("A", "G1");
Book secondMatchingBook = new Book("C", "G1");
manager.Add(secondMatchingBook);
manager.Add(new Book("B", "G2"));
manager.Add(firstMatchingBook);
List<Book> filteredBookList = manager.GetBooksInGenre("G1");
Assert.AreEqual(2, filteredBookList.Count);
Assert.AreEqual(firstMatchingBook, filteredBookList[0]);
Assert.AreEqual(secondMatchingBook, filteredBookList[1]);
}
All I did was the switch up the order I added the books. The output, once the functionality is implemented, should be the same as in the previous tests. I implement the functionality in BookListManager like this:
public List<Book> GetBooksInGenre(string genre)
{
return GetSortedBookList().FindAll(delegate(Book book)
{
return book.Genre == genre;
});
}
All I had to do was the pre-sort the list! I love when I can build on existing functionality. This happens a lot when you build small, fine-grained methods. You end up being able to use them in new and interesting combinations to implement new functionality easily.
Conclusion
When I sat down to write this episode, I truly thought it was going to be 2 or 3 tests, a couple hundred words, and a bit of code. When I got into it, though, I found several other tests to write, a need to write and use the Equals method for Book, and a bit of refactoring. I always find it interesting how complexity just shows up and how easily it is handled.
As an observation, you may have noticed that I have 68 lines of source code, almost all of it completely and totally trivial methods, and about 190 lines of test code. That ratio is a little skewed, because I haven’t had any really good functionality to implement, but I’m not upset about it at all. I’m certain that the 68 lines of source work, and I can continue to leverage the 190 lines of test code forever to confirm that the lines continue to work. I consider that to be an investment well worth the effort.
The next episode will add another user story to the mix. I think I’ll do the last one in the list, retrieving a list of books sorted by genre and title.
Until we meet again!
— bab
Saturday, November 03, 2007
#
Title: Solution to Class Exercise
As described in class:
I have books — too many books. They are all over the floor, I trip over them. I can’t keep track of all the different books I have. I really need a book list manager. Please build one for me.
Here is the list of stories I give the students, and I ask for them in somewhat random order.
I should be able to see a list of my books, sorted alphabetically by title
I should be able to see all books in a specific genre
I should be able to read in a list of books from a text file
I need to know the current price of a book
I want to sort books according to price
I want to be able to add a new book to my list
I want to be able to save my list of books to a text file
I want to be able to mark books as having been read
I want to be able to find which books have been read
I want to sort books by genre and title
BookID |Title |Genre |HasBeenRead
1 |Clifford Goes To College |Childrens |Y
2 |Have Space Suit, Will Travel |ScienceFiction |N
3 |Goedel, Escher, and Bach |Science |N
4 |Elegant Universe |Science |Y
5 |Life in 1000 AD |History |N
6 |1001 Ways to Cook a Cat |Cooking |N
Story 1 — Give me a list of books sorted by title
Most basic functionality in system. I just need to get a list of my books. I’ll invent some way to get a list of books into my system later, but for now, assume I have a list, and show them to me in some way sorted alphabetically.
I start by writing a test, being the good TDD programmer. Here is my first test:
[TestFixture]
public class BookListManagerFixture
{
[Test]
public void EmptyBookListReturnsNothing()
{
BookListManager manager = new BookListManager();
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.IsEmpty(sortedBookList);
}
}
This is the simplest test I can write to get the ball rolling. I’m starting to get the feel for the API, seeing how to create a BookListManager, how to talk to it, and its basic empty behavior. It’s pretty apparent to me that I’m going to be managing a list of 0 or more books. When I am presented with a problem that requires me to handle many items, I generally try to handle three cases, in this order:
- 0 - Let’s me get the problem set up, and get feel of the API
- 1 - Gets the business logic in the problem correct
- many - Makes me write the looping logic for already working business logic.
And now the simple code to get the previous test to compile. I created an empty Book class. I guess I don’t strictly need a Book class yet, but this application is all about managing lists of books. I’m willing to go out on a limb to guess about a book class, but I don’t know what is in yet.
public class Book
{
}
Here is the first shot at a BookListManager. Basic, simple, doesn’t do anything yet. It exists just to fail my test.
public class BookListManager
{
public List<Book> GetSortedBookList()
{
return null;
}
}
This leads me to implement the simplest code I can to get this test to pass:
public class BookListManager
{
public List<Book> GetSortedBookList()
{
return new List<Book>();
}
}
Now my GetSortedBookList class returns an empty list, which allows my test to pass, trivially. An important thing to note, however, is that I’m making a statement about how my code acts when the collection it is asked to sort is empty. This behavior has to work now, it has to work tomorrow, and it has to work forever. If I were to skip writing this test, I’d always have that nagging doubt about how my system acted in this situation.
Rule — Always write tests for trivial boundary condition cases. They have to work, so they need tests. The tests are easy to write, so write ‘em!
Now the test for a single item in the list. Again, this test should be trivial, but we have to document and prove the behavior for this case, which requires a test to be written.
[Test]
public void SingleBookInListIsReturnedAsSortedList()
{
BookListManager manager = new BookListManager();
manager.Add(new Book());
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.IsNotEmpty(sortedBookList);
}
So, this is a logical second test. I needed to add a book into my list somehow, and I found one of the many ways to do this. There are several ways to get the book into the system, some of them better than others. The easiest way of doing it is to just add an Add method to the BookListManager. This way, you can add new books to the list in the Arrange section of your test, putting the test data and test behavior in the same place, which is always a good thing.
The assert in this test just checks to make sure that there is something in our list of books, which is OK, but is not what I would consider to be a strong assertion. What we really mean is that there is a book, and, in fact, it is the same book as we put in. Since we’re sorting based on title, perhaps this is a good time to give a book a Title property, to allow us to assert a bit more about this solution.
[Test]
public void SingleBookInListIsReturnedAsSortedList()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("My Title"));
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.AreEqual(1, sortedBookList.Count);
Assert.AreEqual("My Title", sortedBookList[0].Title);
}
}
This test is essentially the same, but it has a stronger assertion — the output list has a single element in it, and that element has the same title as the book that we put in. That’s about the strongest assertion that we can make at this point. Note that I didn’t use Assert.AreSame to ensure that the Book object put into the list and the Book object returned from the list are the same object, as that would imply an implementation decision. Eventually, I’m going to want to implement Book.Equals, so I don’t have to manually compare books by inspecting their properties.
Implementing this functionality is trivial:
public class Book
{
private readonly string title;
public Book(string title)
{
this.title = title;
}
public string Title
{
get { return title; }
}
}
public class BookListManager
{
private readonly List<Book> bookList = new List<Book>();
public List<Book> GetSortedBookList()
{
return bookList;
}
public void Add(Book book)
{
bookList.Add(book);
}
}
OK, now its time for the many test. Here is my first shot at this test. Note that this is wrong, wrong, wrong.
[Test]
public void MultipleBooksAreReturnedInSortedByTitleOrder()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("AAA"));
manager.Add(new Book("BBB"));
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.AreEqual(2, sortedBookList.Count);
Assert.AreEqual("AAA", sortedBookList[0].Title);
Assert.AreEqual("BBB", sortedBookList[1].Title);
}
This looks like a pretty reasonable test to write, and it is, save for one important detail. It won’t ever fail. Many a rookie (and experienced!) TDD’er has left out the step of watching a test fail before implementing it. In this case, this test would have passed the first time it was run. When that happens, you should immediately react by thinking, “Huh? WTF?” Tests that pass the first time should be viewed with lots and lots and lots of skepticism. In this case, we added to books to the BookListManager in pre-sorted order, so no sorting was necessary to make the test pass. Since writing the sorting behavior is an important part of the method we’re writing, and the test isn’t forcing us to write any sorting behavior at all, I’d say this was a bad test. 2 lessons to take from this:
Always watch your tests fail before implementing the logic
Care must be taken when crafting test data to have it force you down the path you need to take
Let’s try that test one more time, with better test data, and watch it fail:
[Test]
public void MultipleBooksAreReturnedInSortedByTitleOrder()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("BBB"));
manager.Add(new Book("AAA"));
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.AreEqual(2, sortedBookList.Count);
Assert.AreEqual("AAA", sortedBookList[0].Title);
Assert.AreEqual("BBB", sortedBookList[1].Title);
}
}
There was a little bit of work necessary to get this test to pass. My first attempt was to add a bit of code to the BookListManager.Sort method:
public List<Book> GetSortedBookList()
{
bookList.Sort();
return bookList;
}
First of all, I hate this code. I hate for about 92 different reasons. The first is that I hate having to separate the two lines of implementation, but List.Sort() returns void. Second, and equally hateful, is that it sorts the list in place. What I would really like is List<T> List<T>.Sort(), a method that Sorts the underlying list and returns me a sorted copy of it, leaving the original list untouched. I have a feeling they made this choice because it gives me the option of copying the list first by myself or just sorting the list in place. If they did what I was suggesting, then there would be no way to sort a list in place, which may be a desired behavior in some cases. Hey, developing software is all about making choices, right? I do have a solution to the problem involves using Extension Methods from C# 3.5 that I’ll post another day.
The other thing I didn’t like about this code is that it didn’t work :( My problem is that the Sort() method requires that the objects being sorted be comparable in some way. The easiest way is to make my Book class implement IComparable, or I could create a BookComparator that implements IComparator and move this functionality outside of Book itself. I chose the former, as it seems simpler for right now. This required me to write some code in the Book class, which is a danger sign.
A fixture for one class should not force you to add code into a different class. Write a separate fixture. The first fixture describes the need, the second fixture drives the implementation.
Since I need to add functionality into the Book class, I really need a BookFixture. I’m going to comment out my original test, create the functionality I need in the BookFixture, and then return to my original test. This jumping from test to test is actually very common. Here is my BookFixture and Book code to implement IComparable:
[TestFixture]
public class BookFixture
{
[Test]
public void BookWithTitleBeforeSecondBookReturnsNegativeCompareToValue()
{
Book before = new Book("A");
Book after = new Book("B");
Assert.Less(before.CompareTo(after), 0);
}
[Test]
public void BookWithTitleAfterSecondBookReturnsPositiveCompareToValue()
{
Book after = new Book("B");
Book before = new Book("A");
Assert.Greater(after.CompareTo(before), 0);
}
[Test]
public void BooksWithSameTitleReturnZeroCompareToValue()
{
Book same1 = new Book("A");
Book same2 = new Book("A");
Assert.AreEqual(0, same1.CompareTo(same2));
}
}
public class Book : IComparable<Book>
{
private readonly string title;
public Book(string title)
{
this.title = title;
}
public string Title
{
get { return title; }
}
public int CompareTo(Book other)
{
return title.CompareTo(other.title);
}
}
That’s some pretty exhaustive testing! To be very honest, the second and third tests passed the first time I ran them. I kind of expected that, as I had only one line of code to write to invoke the correct CompareTo behavior for the entire class, and I wrote that to get the first test to pass. I still wrote the remaining tests, and I’d recommend that anyone else write these tests, as a way of clearly documenting the correct behavior. I have to admit that I always forget how CompareTo works with respect to which way the comparison works. I figure that if I have a problem with it, others may also, so I document the daylights out of it ;)
Now when we go babck to our original test, it works now that I’ve implemented the IComparable functionality on Book.
Here is the final BookListManagerFixture and BookListManager code to go with the BookFixture and Book classes above:
[TestFixture]
public class BookListManagerFixture
{
[Test]
public void EmptyBookListReturnsNothing()
{
BookListManager manager = new BookListManager();
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.IsEmpty(sortedBookList);
}
[Test]
public void SingleBookInListIsReturnedAsSortedList()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("My Title"));
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.AreEqual(1, sortedBookList.Count);
Assert.AreEqual("My Title", sortedBookList[0].Title);
}
[Test]
public void MultipleBooksAreReturnedInSortedByTitleOrder()
{
BookListManager manager = new BookListManager();
manager.Add(new Book("BBB"));
manager.Add(new Book("AAA"));
List<Book> sortedBookList = manager.GetSortedBookList();
Assert.AreEqual(2, sortedBookList.Count);
Assert.AreEqual("AAA", sortedBookList[0].Title);
Assert.AreEqual("BBB", sortedBookList[1].Title);
}
}
public class BookListManager
{
private readonly List<Book> bookList = new List<Book>();
public List<Book> GetSortedBookList()
{
bookList.Sort();
return bookList;
}
public void Add(Book book)
{
bookList.Add(book);
}
}
Next up
In the next installment, I’ll take a book list and filter it by genre. Coming soon to a theater near you :)
— bab
Wednesday, October 31, 2007
#
I gave an introduction to Powershell talk at the St. Louis .Net UG meeting on Monday, October 29th to about 70-80 people or so. I introduced basic concepts of powershell, talked about a few problems I had solved with it, and showed some simple scripts.
At the end of the presentation, I promised to post the slides by the end of this week, and I'm making it Wednesday night. Believe me when I say that me getting something finished early is a minor miracle :)
-- bab
Tuesday, October 23, 2007
#
I was using the new xunit.net testing framework, and I wanted to see a list of all the attributes they had. This looks like a job for Powershell!!!
[System.Reflection.Assembly]::LoadFile("pathToFile.dll").GetTypes() | where-object { $_ -match "Attribute" }
That did the trick!
-- bab
Monday, October 22, 2007
#
I was repaving a machine the other day, and I had to load all my development tools. There were a bunch of them, and when I got finished, I noticed that IIS and SQL Server failed to install properly. So I uninstalled IIS and reinstalled it, no problem. SQL Server was another story.
I uninstalled it, and it only went part way. Then I tried to reinstall it, and it said it was already installed. I went around and around like this a few time, with a few reboots thrown in for good measure.
About this time, I started to google around for how to manually uinstall SQL Server. I came across a KB article on msdn.com somewhere, and it said to crawl through the registry in HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall, inspect all the GUIDs found there for those that had a DisplayName that contained SQL Server as part of it. Once I found a matching GUID, I was to use the UninstallString to manually uninstall it.
The only problem was that there were dozens of these GUIDs in there. I sure wasn't going to crawl through them all by hand.
So, what was a handy shell programmer to do? Well, I pulled out powershell and whipped up a script.
dir HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall | foreach-object {get-itemproperty $_.PSPath} | where-object {$_.DisplayName -match "SQL Server"} | select-object DisplayName,uninstallstring
Taking this script apart, piece by piece...
dir HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall lists all the registry keys beneath that location. It doesn't just spit out a string name for each item like a Unix shell would, it returns a list of RegistryKey objects. These objects are passed to the next command in the pipeline...
foreach-object {get-itemproperty $_.PSPath} is basically a for loop over each of those objects. It looks at the PSPath property of the RegistryKey objects and calls get-itemproperty on that path to return a list of registry items.
where-object {$_.DisplayName -match "SQL Server"} selects just those registry items where the DisplayName property of the registry items match "SQL Server". Finally, we clean up the output...
select-object DisplayName,uninstallstring essentially takes the objects that are passed to it from the previous pipeline stage and slices them into smaller pieces, creating a new object for each object passed to it. The new object contains just the two properties specified on the command, DisplayPath and UninstallString.
Running this command gives me this output:
DisplayName UninstallString
----------- ---------------
GDR 1406 for SQL Server Integration Services 2005 (64-bi... C:\WINDOWS\DTS9_KB932557_ENU_64\Hotfix.exe /Uninstall
GDR 1406 for SQL Server Notification Services 2005 (64-b... C:\WINDOWS\NS9_KB932557_ENU_64\Hotfix.exe /Uninstall
GDR 1406 for SQL Server Analysis Services 2005 (64-bit) ... C:\WINDOWS\OLAP9_KB932557_ENU_64\Hotfix.exe /Uninstall
GDR 1406 for SQL Server Reporting Services 2005 (64-bit)... C:\WINDOWS\RS9_KB932557_ENU_64\Hotfix.exe /Uninstall
GDR 1406 for SQL Server Database Services 2005 (64-bit) ... C:\WINDOWS\SQL9_KB932557_ENU_64\Hotfix.exe /Uninstall
GDR 1406 for SQL Server Tools and Workstation Components... C:\WINDOWS\SQLTools9_KB932557_ENU_64\Hotfix.exe /Uninstall
Microsoft SQL Server 2005 (64-bit) "C:\Program Files\Microsoft SQL Server\90\Setup Bootstra...
Microsoft SQL Server Setup Support Files (English) MsiExec.exe /X{18C5A65B-0A39-40B5-B958-63055AFAB65C}
Microsoft SQL Server VSS Writer MsiExec.exe /I{50822200-2E95-4E62-A8D8-41C3B308DF5E}
Microsoft SQL Server 2005 Analysis Services (64-bit) MsiExec.exe /I{54C2B4E9-DD13-4AA4-B09A-A6EF68F9359A}
Microsoft SQL Server Native Client MsiExec.exe /I{6E740973-8E71-42F9-A910-C18452E60450}
Microsoft SQL Server 2005 Integration Services (64-bit) MsiExec.exe /I{8A52D844-0DA7-40B0-8602-0567C068C081}
Microsoft SQL Server 2005 Reporting Services (64-bit) MsiExec.exe /I{BEE3EC3D-0C91-4A3E-A42C-7634D32968F4}
Microsoft SQL Server 2005 Backward compatibility MsiExec.exe /I{C92556F2-4950-48CF-ABA3-F0026B05BCE8}
MySQL Server 5.0 MsiExec.exe /I{D84E063A-AE58-41AF-B6FC-313B12DC89A6}
Microsoft SQL Server 2005 Notification Services (64-bit) MsiExec.exe /I{EA145881-7452-4004-80B9-971FC3D1D8D8}
Microsoft SQL Server 2005 (64-bit) MsiExec.exe /I{F14F2E25-99AF-42A9-977C-F6D0352DC59F}
Microsoft SQL Server 2005 Tools (64-bit) MsiExec.exe /I{FE7C8861-3195-4CA5-98EB-094652478192}
which is exactly what I wanted to find out in the first place. If I wanted to go further, I could run the uninstall command for these things automatically, but since I only had about 3 items I had to reinstall in my case, doing it by hand was no big deal.
Anyhow, consider this published so that when I need this trick next time, it will be waiting here, safe and sound, on my blog, ready for me to read again.
-- bab
Monday, September 24, 2007
#
My wife, Sharon, and I were talking about our top 10 movie list and what would be on it. The requirements were pretty simple. These had to be movies that we would generally stop what we were doing and watch together. Just because one of us like it wasn’t enough to make the list — it had to be both.
Here they, are in random order:
- A Few Good Men
- Field of Dreams
- The Shawshank Redemption
- Bull Durham
- Remember the Titans
- Top Gun
- Back to the Future
- Men In Black
- Breakfast Club
No real point to this post, but I thought I’d share :)
— bab
Sunday, September 23, 2007
#
I’m a few days late to this party, but my friends Jim Newkirk and Brad Wilson have released a [new .Net testing framework(http://www.codeplex.com/xunit). What is interesting about this framework is that it is built based on many years of combined experience between Jim and Brad, with input, I’m sure, from Scott, Peter, and others.
Jim and Brad made some interesting choices, like removing SetupAttribute and TearDownAttribute, but they’ve defended their choices.
Go check it out. And while you’re there, please vote for adding an adapter to allow xUnit tests to be run through ReSharper. You can do this by logging into CodePlex, or creating an account if you’ve never logged in, and going to here to vote. Having this in ReSharper would make my .Net development complete :)
Last point, if any of you are developing .Net code, and you are not using ReSharper, why the !@#$!@# not??? Give yourself a treat and check it out.
— bab
Monday, September 17, 2007
#
OK, so this stuff is different. Really different. So different that i feel like a TDD rookie all over again. I find myself questioning everything that I do, and wondering if I’m going in the right direction. But it’s fun learning something new…
When I last left you…
When we finished episode 1, we had created a couple of customer tests and had used Interaction Based Testing to drive out the basics of our architecture. In looking back at what we drove out, I wonder about some of those classes. I can see that I have an input side, and processing middle, and an output side, but I see an awful lot of generalization having happened already. I’m going to watch out for this throughout the rest of this exercise. It is possible that this style of writing tests drives you towards early generalization, but I’m pretty sure it is just my unfamiliarity with how to drive code through these tests that is making this happen.
The Input Side
According to the first test I wrote, this is the interface that the input side needs to have:
public interface IInputReader
{
List<BatchInput> ReadAllInputs();
}
I don’t know anything about a BatchInput yet, or how to read the input lines, but I think I may be about to find out.
So my job now is to drive out how the IInputReader will be implemented by some class. As it turns out, this is really not very interesting. The interaction-based testing that we’ve been doing has been very useful at driving out interactions, but the InputReader seems to stand alone. It is at the very end of the call chain, which means that it doesn’t interact with anything else. This means that state-based tests will do just fine to test this piece of the system.
Here is the first test I wrote for this class:
[Test]
public void InputReaderImplementsIInputReader()
{
Assert.IsInstanceOfType(typeof(IInputReader), new InputReader(null));
}
I’ve started writing tests like these to force me to make the class I’m writing implement a specific interface. I started doing this because I’ve found myself going along writing a class, knowing full well that it has to implement some interface, but forgetting to actually do it. I end up writing the whole class to the wrong API, and I have to go back and refactor the API to match what it should be. Hence, I write this test now to enforce me implementing the right interface.
Here are the rest of the tests:
[Test]
public void EmptyInputStreamGeneratesEmptyOutputList()
{
StringReader reader = new StringReader(String.Empty);
InputReader inputReader = new InputReader(reader);
List<BatchInput> input = inputReader.ReadAllInputs();
Assert.AreEqual(0, input.Count);
}
[Test]
public void SingleCommandInputStringGeneratesSingleElementOutputList()
{
StringReader reader = new StringReader("a|b" + System.Environment.NewLine);
InputReader inputReader = new InputReader(reader);
List<BatchInput> input = inputReader.ReadAllInputs();
Assert.AreEqual(1, input.Count);
Assert.AreEqual("a|b", input[0].ToString());
}
[Test]
public void MultipleCommandInputStringGeneratesMultipleElementsInOutputList()
{
StringReader reader = new StringReader("a|b" + System.Environment.NewLine + "b|c" + Environment.NewLine);
InputReader inputReader = new InputReader(reader);
List<BatchInput> input = inputReader.ReadAllInputs();
Assert.AreEqual(2, input.Count);
Assert.AreEqual("a|b", input[0].ToString());
Assert.AreEqual("b|c", input[1].ToString());
}
These tests follow the usual 0, 1, many pattern for implementing functionality. Make sure something works for 0 elements, which fleshes out the API, then make sure it works for a single element, which puts the business logic in, and then make it work for multiple elements, which adds the looping logic. Here is the oh, so complicated code to implement these tests:
public class InputReader : IInputReader
{
private readonly TextReader reader;
public InputReader(TextReader reader)
{
this.reader = reader;
}
public List<BatchInput> ReadAllInputs()
{
List<BatchInput> inputData = new List<BatchInput>();
ReadAllLines().ForEach(delegate(string newLine)
{ inputData.Add(new BatchInput(newLine)); });
return inputData;
}
private List<string> ReadAllLines()
{
List<string> inputLines = new List<string>();
while (reader.Peek() != -1)
{
inputLines.Add(reader.ReadLine());
}
return inputLines;
}
}
And that should pretty well handle the input side of this system.
On to the Processor
The Processor class takes the input BatchInput list and converts it into ProcessOutput objects, which are then written to the output section of the program. Here is the interface again that rules this section of code:
public interface IProcessor
{
List<ProcessOutput> Process(List<BatchInput> inputs);
}
First of all, let’s make sure that my class is going to implement the correct interface:
[Test]
public void ProcessorImplementsIProcessor()
{
Assert.IsInstanceOfType(typeof(IProcessor), new Processor(null, null));
}
Now, the responsibilities that seem to have to happen here are that each BatchInput object needs to be turned into something representing a payroll input line, and that new object needs to be executed in some way. Those thought processes lead me to this test:
[Test]
public void SingleBatchInputCausesStuffToHappenOnce()
{
MockRepository mocks = new MockRepository();
IPayrollProcessorFactory factory = mocks.CreateMock<IPayrollProcessorFactory>();
IPayrollExecutor executor = mocks.CreateMock<IPayrollExecutor>();
Processor processor = new Processor(factory, executor);
PayrollCommand commonPayrollCommand = new PayrollCommand();
List<BatchInput> batches = TestDataFactory.CreateBatchInput();
using (mocks.Record())
{
Expect.Call(factory.Create(batches[0])).Return(commonPayrollCommand).Repeat.Once();
executor.Execute(commonPayrollCommand);
LastCall.Constraints(Is.Equal(commonPayrollCommand)).Repeat.Once();
}
using (mocks.Playback())
{
processor.Process(batches);
}
}
There is tons of stuff to see in this test method now. Immediately after I create my MockRepository, I create my system. This consists of three objects:
- IPayrollProcessorFactory — responsible for converting the BatchInput object into a PayrollCommand
- IPayrollExecutor — responsible for executing the PayrollCommand after it is created
- Processor — the driver of the system
Together, these three classes make up this portion of our system. If I were doing SBT (state-based testing), I’m not entirely sure at all that I would have these two embedded objects yet. I would probably have written code and then refactored to get to where I am now. But, with IBT, you have to think in terms of who the collaborators are that the method under test is going to use, and jump to having those collaborators now rather than later. In fact, the whole IPayrollExecutor seems kind of contrived at this point to me, but I need to have something there to interact with, so I can write an IBT for this.
On the next line, I create an instance of my PayrollCommand. I specifically use this instance as the returned value from the factory.Create call in the first expectation and as a constraint to the executor.Execute in the second expectation. This was something I was struggling with earlier in my experimentation with IBT. What I want to have happen is that I want to force my code to take the object that is returned from the Create call and pass it to the Execute call. By having a common object that I use in the expectations, and having the Is.Equal constraint in the second expectation, I can actually force that to happen. It took me a while to figure this out, and I’m pretty sure that this is a Rhino Mocks thing, rather than a generic IBT thing, but I found this to be helpful.
Then I drop into the record section, where I set some expectations on the objects I’m collaborating with. The first expectation says that I expect an instance of a BatchInput to be provided to this Execute method when called. Please note, and it took me a while to intellectually really grasp this, the batches[0] that I’m passing to the Create method is really just a place holder. This is the weird part here — I’m not actually calling the factory.Create method here, I’m signaling the mocking framework that this is a method I’m about to set some expectations on. I could have just as easily, in this case, passed in null in place of the argument, but I thought null didn’t communicate very clearly. What I do mean is that I expect some instance of a BatchInput to be provided to this method. Maybe I would have done better by new’ing one up in place of using batches[0]???? It is not the value or identity of the object that matters here at all, it is the type, and only because a) the compiler needs it and b) it communicates test intent. The rest of that expectation states that I’m only going to expect this method to be called once, and is allowing me to specify what object will be returned when this method is called. This last part is one of the hardest parts for me to have initially grasped. I was unsure whether this framework was asserting that the mocked method would return the value I passed it, or whether it was allowing me to set up the value that would be returned when it was called. In looking back, the second option is the only one that makes any sense at all, since these expectations are being set on methods that are 100% mocked out and have no ability to return anything without me specifying it in some way. Doh!
The second expectation is where I set up the fact that I expect the same object that was returned from the Create call to be the object passed to this call. Again, I do this through the Constraint, not through the value actually passed to the executor.Execute() method. I could just as easily passed in null there, but it wouldn’t have communicated as clearly.
Finally, I get to the playback section, call my method, and the test is over.
This is the code that I wrote to make this test pass:
public List<ProcessOutput> Process(List<BatchInput> batches)
{
List<ProcessOutput> results = new List<ProcessOutput>();
PayrollCommand command = factory.Create(batches[0]);
executor.Execute(command);
return results;
}
I know I’m not handling the results at all yet, but I’m pretty sure I can flesh out what will happen with those at some point soon.
In my second test, I’ll worry about how to handle multiple BatchInput objects. Again, this is a very common pattern for me, starting with one of something to get the logic right, and then moving on to multiple, to put in any looping logic I need. Here is the second test:
[Test]
public void MultipleBatchInputsCausesStuffToHappenMultipleTimes()
{
MockRepository mocks = new MockRepository();
IPayrollProcessorFactory factory = mocks.CreateMock<IPayrollProcessorFactory>();
IPayrollExecutor executor = mocks.CreateMock<IPayrollExecutor>();
Processor processor = new Processor(factory, executor);
PayrollCommand commonPayrollCommand = new PayrollCommand();
List<BatchInput> batches = TestDataFactory.CreateMultipleBatches(2);
using (mocks.Record())
{
Expect.Call(factory.Create(batches[0])).
Constraints(List.OneOf(batches)).Return(commonPayrollCommand).Repeat.Twice();
executor.Execute(commonPayrollCommand);
LastCall.Constraints(Is.Equal(commonPayrollCommand)).Repeat.Twice();
}
using (mocks.Playback())
{
processor.Process(batches);
}
}
Almost all of this test is exactly the same, except I add two BatchInput objects to my list. The only other thing I need to enforce is that the object that is passed to the factory.Create method is a BatchInput object that is a member of the list I passed in, which I do with the List Constraint to the first expectation.
Here is the modified Processor code:
public List<ProcessOutput> Process(List<BatchInput> batches)
{
List<ProcessOutput> results = new List<ProcessOutput>();
foreach (BatchInput batch in batches)
{
PayrollCommand command = factory.Create(batch);
executor.Execute(command);
}
return results;
}
Object Mother
In both of these tests, you’ll see a reference to TestDataFactory. This is a class whose responsibility it is to create test data for me when asked. I use it to remove irrelevant details about test data from my tests and move it someplace else. This is called the Object Mother pattern.
In the next episode…
That’s about enough for now. If any of this wasn’t clear, please let me know, and I’ll update the text to be better. In the next episode, I’ll go ahead and build the factory using SBT, since it isn’t going to interact with anything and then dive into the Processor code, which should prove interesting.
Overall, I’m pretty happy with how IBT is allowing me to focus on interactions between objects and ignore details like the contents of my domain classes entirely until I get to a class who manipulates the contents of those domain classes.
My biggest question lies in the area of premature generalization. Am I thinking too much and ignoring YAGNI? Do these tests reflect the simplest thing that can possibly work? I’m truly not sure. I tried to do better in this episode to focus on just payroll stuff and not make generic classes, like the IInputReader. I have a PayrollProcessorFactory, for example, instead of a ProcessorFactory. Those refactorings will come, and I want to wait for the code to tell me about them. IBT, I think, makes it easier to see those abstractions ahead of time, but I need to resist!
Please write with questions and comments. This continues to be an interesting journey for me, and I’m not at all sure where I’m going yet! But it is fun!
— bab
Monday, September 10, 2007
#
My friend, Jim Newkirk, introduced me to a very nice way of partitioning programmer tests for a class as you write them. Most developers write a single test class for a single application class, and just dump all tests for that class in the same place. This is not as correct as it could be (that’s Consultant-Speak for “that’s just plain wrong”).
The accepted best practice is to group together tests that have the same setup/teardown logic into the same test fixtures, which can lead to having multiple fixtures for a single class. For example, when I build a Stack class, I generally have different fixtures for each of the different states that my Stack class can have, and I put a test into the correct fixture representing its starting state. For example, I might have states corresponding to
- an empty stack
- stack with a single element
- stack with multiple elements
- stack that is full
and so on. I would create a new fixture for each of these states, and use setup and teardown to push my system into the given state for that fixture. I know that this is a departure from my previous advice about Assiduously Avoid Setup and Teardown, but I think I like where this leads me. I promise to post an example of writing tests like this over the next few days, but that example is not part of what I’m talking about here.
What I am talking about is an arrangement like this:
[TestFixture]
public class StackFixture
{
[TestFixture]
public class EmptyFixture
{
[Test]
public void ATest() {}
}
[TestFixture]
public class SingleElementFixture
{
[Test]
public void AnotherTest() {}
}
}
and so on. The main reason I like this arrangement of using nested fixtures is that it allows for me to separate out tests for different behaviors of my class into different fixtures, which lets me find them more easily and makes it easier to decide where to put new tests, and it lets me run all the tests for a particular class together at the same time. If I were to have several independent test fixtures, I would have no automated way of ensuring that I ran all of them together. The closest I could come would be to use categories, which is rather manual and error prone.
Now, what I just tried to do was to replicate this arrangement in Java, and it was harder to make it work. Using JUnit 3.8.1, I tried this:
public class StackFixture extends TestCase {
public static class EmptyFixture extends TestCase {
public void testATest() {}
}
}
This gave me two tests run, one failing, so it found the test in the inner class, but found an error about no test being found in the outer fixture, StackFixture, so my tests could never all pass. I tried removing static from the class declaration, and then JUnit didn’t find the test in the inner fixture, and I still had the failure for no tests found. Clearly, not possible here.
Then I tried JUnit 4, which, like NUnit 2 and beyond, uses attributes to identify tests. In Java, they call them annotations, but they seem to be the same thing. Here is what I wrote:
public class JUnitFourFixture {
public class StackEmptyFixture {
@Test
public void EmptyAtCreation() {
Stack stack = new Stack();
assertTrue(stack.isEmpty());
}
}
}
When I ran this, I got an error popup saying that there were no tests found. Not a winner :( But when I added static to the class declaration for the inner class, things did finally work beautifully. Here is the code that worked, with an extra fixture added just to be sure, and the inner classes made static. (BTW, for those of you who don’t know, there are two kinds of inner classes in Java. Inner classes without the static prefix belong to a particular instance of the enclosing class, so when you instantiate the outer class, you’re instantiating the inner class as well, and it has access to stuff in the outer object. If you have the static prefix, then the inner class is entirely independent of the outer class, just like inner classes in C#.)
public class JUnitFourFixture {
public static class StackEmptyFixture {
@Test
public void EmptyAtCreation() {
Stack stack = new Stack();
assertTrue(stack.isEmpty());
}
}
public static class SingleElementFixture {
@Test
public void AnotherTest() {
assertTrue(true);
}
}
}
I don’t know how many of you didn’t know this, or never had a reason to care about this, but I am teaching a Java TDD course this week. Before I taught this, I wanted to make sure it worked!
— bab
Sunday, September 02, 2007
#
So let’s begin our reimplementation of the sample payroll system introduced previously. Briefly, the problem stated that I had a batch payroll system that I needed written to pay the few employees that I had right now for my small company. They are all salaried as of now, but I can imagine hiring some hourly employees later.
Story number one said that, “As the owner, I want to be able to run payroll so that I can pay my employees”. Further clarification said that I have an input file that consists of single-line commands:
Payroll|05/01/2007
Payroll|05/15/2007
Payroll|06/01/2007
When reading this input file, the system should create a single output file containing all paychecks to be written to my employees for each date in the input file that is the first of the month. Having this batch payroll input file allows me, the customer, to run and rerun payroll to my heart’s content.
I also have an output file that I pass off to some other company who creates checks for me. The format of the output file looks like this:
Check|100|Frank Furter|$1000|05/01/2007
Check|101|Howard Hog|$2000|05/01/2007
Check|102|Frank Furter|$1000|06/01/2007
Check|103|Howard Hog|$2000|06/01/2007
Check is a keyword specifying that this is a check payment line, followed by a check number, the name of the person to whom the check should be written, the amount, and the paydate.
So that’s what I need. (Incidentally, as I went back and reviewed the first installment of this from 2004, I found a bug in the specifications. The check number (100-103 above) is supposed to be strictly increasing. I had it restarting with each pay period in the original write up.) I’d like to have a command-line program that I can write that will read the given input file and create the given output file.
We begin by specifying Customer Tests
One change in my development practices since 2004 is that I’ve become committed to having customer tests to define all work that I do. Since I’ve specified some behavior for my system, I’ll need to define a few customer tests to verify that the system is doing the right thing. Fortunately for us, this system is completely command-line driven, so it will be easy to write these customer tests using NUnit. Here are those tests:
[TestFixture]
public class ATFixture
{
[Test]
[Ignore("AT not implemented yet")]
public void All_employees_are_paid_on_first_of_month()
{
StringReader inputs = new StringReader("Payday|01/01/2007" + System.Environment.NewLine);
StringWriter outputs = new StringWriter();
PayrollSystem payrollSystem = new PayrollSystem(inputs, outputs);
payrollSystem.Run();
Assert.AreEqual("Check|100|Billy Bob|$10000|01/01/2007" + System.Environment.NewLine +
"Check|101|Sally Jo|$20000|01/01/2007" + System.Environment.NewLine, outputs.ToString());
}
[Test]
[Ignore("AT not implemented yet")]
public void No_employees_are_paid_if_provided_date_is_not_the_first_of_the_month()
{
StringReader inputs = new StringReader("Payday|01/02/2007" + System.Environment.NewLine);
StringWriter outputs = new StringWriter();
PayrollSystem payrollSystem = new PayrollSystem(inputs, outputs);
payrollSystem.Run();
Assert.AreEqual("", outputs.ToString());
}
}
Now, I’m cheating ever so slightly here, as I’m not reading and writing files, but using StringReaders and StringWriters. I’m just assuming that I can plug in the files at a later date, and things will just work. Email me if you find this cheat offensive, and I’ll consider adding other tests that really do touch the file system. I’m reluctant to do that, because touching the file system brings its own set of worries with it:
- Where are the files actually located at runtime?
- Do I have read and write permission to the directory where they’re located?
- Who is going to clean up the output file after the test is finished?
- Touching the file system is much slower than doing things in memory
and so on.
These customer tests are pure and simple State Based Tests, because it seems to me that this is the right technology to use at this level. They are state-based because the state of the system is what the user is concerned with — if I pass this into the system, this is what comes out. Makes sense to me. So I have two tests for right now, one specifying what happens on the first of the month, and another specifying what happens on any other day of the month. Between those two tests, this should characterize what this story does (absent error checking, of course, which is left as an exercise for the reader).
One final note — these tests are written assuming a very simple API for accessing our program. It is entirely possible that we’ll learn more about how we use our system as write our programmer tests, which will necessitate us changing our customer tests as we go. This will become less and less frequent the further we go into the project, but we’re at the very start now, and our architecture is very likely to change.
Implementing our first programmer tests
And now we’re off. This is going to mark another change to my development style as practiced 3 years ago. Back then, when I started this problem, I recognized the fact that there was an input section, a processing section, and an output section. I assumed that I could get the input and output sections working in some way when I needed to, so I focused on solving the critical business problem in the middle. My thinking was that by doing this I would be fleshing out the requirements of how the inputs and outputs communicated through the middle. I could then write main after I finished the middle, and then write the input or output code and be finished.
Now, I want to write a single test that goes through the whole system as a whole first, and use that to tease out the important abstractions earlier than I did before. So I am going to start with an interaction based test that flows directly from the customer tests. It will take the single PayrollSystem.Run() method and begin to flesh out how it works. This clearly becomes an act of design. My first test:
[TestFixture]
public class PayrollSystemFixture
{
[Test]
public void CreateControlFlowThroughSystem()
{
MockRepository mocks = new MockRepository();
IInputReader reader = mocks.CreateMock<IInputReader>();
IOutputWriter writer = mocks.CreateMock<IOutputWriter>();
IProcessor processor = mocks.CreateMock<IProcessor>();
PayrollSystem payrollSystem = new PayrollSystem(reader, processor, writer);
List<BatchInput> inputs = new List<BatchInput>();
List<ProcessOutput> outputs = new List<ProcessOutput>();
using(mocks.Record())
{
Expect.Call(reader.ReadAllInputs()).Return(inputs).Repeat.Once();
Expect.Call(processor.Process(inputs)).Return(outputs).Repeat.Once();
writer.WriteAllOutputs(outputs);
LastCall.On(writer).Repeat.Once();
}
using(mocks.Playback())
{
payrollSystem.Run();
}
}
}
Just writing this test has already taught me something new about my PayrollSystem class. In my customer tests, I had just the TextReader and TextWriter passed into the PayrollSystem. Now, in thinking more about the problem from a design point of view, I’m finding that there are other pieces that should be passed in. This doesn’t mean that the constructor defined in the customer test is wrong, just that I’ve discovered another one possibly.
Let’s look at this test in more detail. This is an interaction based test, as I described a couple of blog postings ago. Its purpose in life is to design the interactions of this class with the classes that are its immediate neighbors. This means that we’re going to have to do some design here, and make some guesses about other interfaces and methods on them. Writing IBTs is truly an act of design :) (I have a few words to say about this process and YAGNI in a moment)
I find that these kinds of tests are much easier to understand if I read them backwards. In this case, the code in the playback section of the test is the code that is being run by the test. In this case, we’re trying to design the interactions of the PayrollSystem.Run() method.
In the record section, we see what we expect this method to do. In our case, it is going to call reader.ReadAllInputs(), which is going to return inputs, which is List. These inputs will be passed along to our processor, which has a Process method that returns outputs, as a List.
This is finally passed to the writer.WriteAllOutputs() method.
This is my first guess at a high-level design for this system, but I’m certainly open and eager to change this if needed. One thing I’m suspicious about is the way that the problem is broken down into three physically separate processing steps. I like this, because it really does keep the inter-step coupling down as much as possible, but it doesn’t quite feel right to me. When I’ve solved this problem in the past, I’ve had a main method, like Run(), that had a loop that called the input side, got a single record, processed it, and the act of processing caused the writing to happen. I guess this is the difference between a streaming design and a procedural, step-by-step design. I’m going to keep an eye out for anything that will guide me towards either of these choices as I go. For right now, I’m going with what I have written.
Above the recording section is where you can define objects that will be used throughout the test. In our case, we’re defining our PayrollSystem and the two lists that we’ve mentioned previously.
Finally, or firstly I you look at it right-side up, we define the mock objects that we’re going to need in our system.
One thing that I’m finding that I like about writing tests this way is that I get to defer implementation decisions about things until the Last Responsible Moment. For example, to get this test to compile, I had to create three interfaces, add a single method to each of them, define empty BatchInput and ProcessOutput classes, and my PayrollSystem class. I made as few decisions about anything as possible while writing this test, and I like that. I have a feeling that I would have had to at least define something about my BatchInput and ProcessOutput classes if I had been doing a state-based test, as well as defined hand-coded stubs for my interfaces.
Let’s look at the code that implements this test.
First attempt at implementation
One complaint about interaction-based testing is that you create the same code twice, once in the expectations of the test, and again in your source code. There is definitely some truth to this. If you look at the code in the Run() method, it is exactly the same as what was in the record section of the test. I don’t think that this is a problem, though. IBTs force you to think at a really high level, forcing out high level abstractions every early. These high-level abstractions are unlikely to change much once you get into your system a bit, so the duplication doesn’t really hurt you. I think it also helps a reader understand how data and control flows through your system, just through reading the tests.
So here is the code I wrote to make this test pass:
public class PayrollSystem
{
private readonly IInputReader reader;
private readonly IProcessor processor;
private readonly IOutputWriter writer;
public PayrollSystem(TextReader inputs, TextWriter outputs)
{
}
public PayrollSystem(IInputReader reader, IProcessor processor, IOutputWriter writer)
{
this.reader = reader;
this.processor = processor;
this.writer = writer;
}
public void Run()
{
List<BatchInput> inputs = reader.ReadAllInputs();
List<ProcessOutput> outputs = processor.Process(inputs);
writer.WriteAllOutputs(outputs);
}
}
What does this test NOT address?
Note that I haven’t done anything at all about date-specific processing. I don’t even have a place to put it yet. This is another one of those things I like about IBT. It seems to me that writing tests in this style is driving me towards putting responsibilities for lower level details down at a lower level. It is doing this by making it difficult for me to write tests for implementation details like date processing. I have other thoughts about how these tests are making me follow the Law of Demeter much more closely and reducing the amount of refactoring that I’m having to do as I write this code. In fact, I’m finding that I’m refactoring my code less now, typically only when I’m changing my mind about how things are structured. The IBTs create systems that are already OO in nature very early, which means that I’m not feeling the need for the post-test-working refactoring step anywhere nearly as much. We’ll see if it continues to work this way as we get further into this.
What about YAGNI?
One concern I have at fleshing out these abstractions so early in my project is that I’m not sure I need them yet. Maybe I could have driven out different, less abstract abstractions (?) by focusing on just payroll behavior, and if so, that would be my fault. But this did feel like the shape of this problem to me, so I went with it. I’m going to watch for premature generalizations throughout this exercise, in an effort to comply with YAGNI.
Next step
OK, so we have the basic high-level design of our system in place. Given our design, I can now start to pick out any one of the three major legs of the design to start working on first, since they’re really totally independent. I’m going to do the input side first, just because its easy, and knock that out in the next installment in the next few days.
Please ask questions
Readers, I beg you.. I’m learning this stuff, too, and I learn best when people challenge me on what I’ve done. Ask me questions if something seems strange or silly. There is every chance that I’ve made some choice that could be better, and we’ll all learn from it as we go.
Thanks for sticking with this post for so long, and I hope it was useful.
— bab
Thursday, August 30, 2007
#
Craig Buchek pointed me to a great paper called, Mock Roles, Not Objects. I thought it was a good explanation of what I was trying to show in my last post.
Recommended reading.
-bab
Wednesday, August 29, 2007
#
Hi, everyone. I haven’t posted any serious technical content on this blog for a long time now. The reason for this is that I’m now a pointy haired boss most of the time. I spend my days teaching, mentoring, coaching, and occasionally pairing with someone on another team. I miss coding… I really do.
However, I’ve been digging into Interaction Based Testing over the past few weeks, and I’ve found it fascinating. The road I took to get here involved trying to learn more about what Behavior Driven Development is, and why so many people I know and respect seem to like it, or at least appreciate it. One of the techniques that BDD uses is something called Interaction Based Testing, or IBT for short.
Interaction Based Testing
IBT is different from traditional TDD in that it is defining and verifying the interactions between objects as they take place, rather than defining and verifying that some input state is being successfully translated to some output state. This latter kind of testing, called State Based Testing, or SBT for short, is what I had always done when I did TDD (for the most part). IBT involves using a Mock Object Framework that allows you to set expectations on objects that your class under test is going to call, and then helps you verify that each of those calls took place. Here is a short example:
[TestFixture]
public class IBTExample
{
[Test]
public void SampleITBTest()
{
MockRepository mocks = new MockRepository();
IListener listener = mocks.CreateMock<IListener>();
Repeater repeater = new Repeater(listener);
listener.Hear("");
LastCall.On(listener).Constraints(Is.NotNull()).Repeat.Once();
mocks.ReplayAll();
repeater.Repeat("");
mocks.VerifyAll();
}
}
The basic problem that I’m trying to solve here is that I can write a method, Repeat(), on a class called Repeater such that when I call Repeat(), it repeats what it was passed to its IListener. The way that I set this up is more complicated than I would use in a state-based test, but I avoid cluttering my test with irrelevant implementation details (like explicit data).
What this test is doing is creating the system and setting expectations on the IListener that define how the Repeater class is going to use it at the appropriate time. The MockRepository is the class that represents the mock object framework I’m using, which in this case is Rhino Mocks. I new one of these up, and it handles all the mocking and verification activities that this test requires. On the next line, you see me creating a mock object to represent an IListener. I typically would have created a state-based stub for this listener that would simply remember what it was told, for my test to interrogate later. In this case, the framework is creating a testing version of this interface for me, so I don’t have to build my own stub. Next, I create the class under test and wire it together with the listener. Nothing fancy there.
The next line looks a little strange, and it is. It is actually a result of how this particular mocking framework functions, but it is easily understood. While it may look like I’m calling my listener’s Hear method, I’m actually not. When you create an instance of the mocking framework, it is created in a recording mode. What this means is that every time you invoke a method on a mocked out object while recording, you are actually calling a proxy for that object and defining expectations for how that object will be called in your regular code later. In this case (admittedly, not the simplest case), listener.Hear() is a void method, so I have to split the setting of expectations into two lines. On the first line, I call the proxy, and the framework makes a mental note that I called it. On the next line, I say to the framework, “Hey, remember that method I just called? Well, in my real code, when I call it, I expect that I am going to pass it some kind of string that will never be null, and I’ll call that method exactly once. If I do these things, please allow my test to pass. If I don’t do them, then fail it miserably”.
After I set up the single expectation I have on the code I’m going to be calling, I exit record mode and enter replay mode. In this mode. the framework allows me to run my real code and plays back my expectations for me while my real code executes. The framework keeps track of whatever is going on, and when I finally call my application method, Repeater.Repeat() in this case, followed by the mocks.VerifyAll(), it checks to make sure that all expectations were met. If they were, I’m cool, otherwise my test fails.
I hope that was at least a little clear. It was very confusing to me, but I sat down with a few folks at the agile conference two weeks ago, and they showed me how this worked. I’m still very new at it, so I’m likely to do things that programmers experienced with this kind of testing would find silly. If any of you see something I’m doing that doesn’t make sense, please tell me!
Here is the code this test is forcing me to write:
public class Repeater
{
private readonly IListener listener;
public Repeater(IListener listener)
{
this.listener = listener;
}
public void Repeat(string whatToRepeat)
{
listener.Hear(whatToRepeat);
}
}
public interface IListener
{
void Hear(string whatToHear);
}
Advantages to IBT style TDD
There are several things about this that I really like:
- It allows me to write tests that completely and totally ignore what the data is that is being passed around. In most state-based tests, the actual data is irrelevant. You are forced to provide some values just so that you can see if your code worked. The values obfuscate what is happening. IBT allows me to avoid putting any data into my tests that isn’t completely relevant to that test, which allows me to focus better on what the test is saying.
- It allows me to defer making decisions until much later. You can’t see it in this example, but I’m finding that I’m much better able to defer making choices about things until truly need to make them. You’ll see examples of this in the blog entries that are to follow (more about this below).
- I get to much simpler code than state-based testing would lead me to
- My workflow changes. I used to
- Write a test
- Implement it in simple, procedural terms
- Refactor the hell out of it
With ITB, I’m finding that it is really hard to write expectations on procedural code, so my code much more naturally tends to lots of really small, simple objects that collaborate together nicely. I am finding that I do refactoring less frequently, and it is usually when I’ve changed my mind about something rather than as part of my normal workflow. This is new and interesting to me.
There are some warts that I’m seeing with it, and I’ll get to those as well, as I write further in this series. I’m also very certain that this technique has its time and place. One of the things I want to learn is where that time and place is. Anyhow, here are my plans for this:
Revisiting my Deep Dive
I want to redo the example I did a couple years ago when I solved the Payroll problem in a 6-part blog series. I want to solve the same problem in a ITB way, and let you see where it leads me. I’ve done this once already, part of the way, just to learn how this worked, and the solution I came up with was very different than the one I did the first time. I’m going to do this new series the exact same way as the old series, talking through what I’m doing and what I’m thinking the whole time. I’m personally very curious to see where it goes.
Once we’re finished, I want to explore some other stories that are going to force me to refactor some of my basic design assumptions, because one of the knocks against ITB is that it makes refactoring harder by defining the interactions inside your tests and your code. We’ll find out.
Please ask questions
I’m learning this stuff as I go, so I’m very eager to hear criticisms of what I’ve done and answer questions about why I’ve done things. Please feel free to post comments on the blog about this and the following entries. I’m really looking forward to this, and I hope you readers are, too.
— bab
Friday, August 10, 2007
#
I'm eagerly looking forward to going to Agile 2007 next week. I look forward to this conference every year to give me energy to get through the next year. It's so much fun to see all my agile friends for a week, hang out, talk about what we've learned, drink the occasional beer, and just catch up.
If you're going to DC this year, look me up. I'm in the conference hotel.
I'd also like to suggest a BDD BoF session, if anyone going is interested in that. I'll try to sign up for it some night there.
Finally, I'm giving 2 talks this year. The first talk is an Experience Report on Tuesday morning. It's about building trust with a customer as a key success factor. On Friday morning, Peter Provost and I are giving a talk called "Agile is more than 'Monkey See, Monkey Do'". The point of this talk is to point out to those who might be new to agile that there is more to it than just the practices, it is possible to be agile without doing ANY of the practices, and that doing the practices doesn't necessarily make you agile.
See you all there!
-- bab
Ayende had an interesting post on his blog today about the only metric that really counts, which is maintainability. He made a joke about measuring this property of a system by measuring the intensity of groans that emanate from the team when asked to changed something, which made me laugh.
It did bring up a more significant question in my mind, one that I've thought about before, and something that I've been telling my TDD classes lately. The question always comes up in class about why we just don't design our systems right in the first place, for some value of right. There are several parts to my answer, but one of them is always that we build our systems simply and change them as we need to so that we can practice changing our systems for our big moment. That big moment happens when the customer comes in and tells us that he really, really, really needs this new feature, and he needs it by next Thursday.
If we had never practiced changing our system, and had never considered changing our system, then this might be a pretty scary thing. But if you build your system such that you practice changing it in new and interesting ways from the first day, when that change request comes in, you yawn and make the change.
In short, you get a maintainable system by practicing maintenance from the first day.
-- bab
Thursday, July 12, 2007
#
I've been preaching TDD for years, and one of the lessons that I've taught over and over is that if a test is hard to write, you have probably bitten off more than you can chew. Comment out this test, try a smaller byte, and come back to this test later.
I need to listen to myself more often :)
Background
It has always been difficult for me to explain to students how TDD works with multiple objects, refactoring, stubs, and the whole shebang. They get the refactoring part, they get the writing a test and them some code part, but their understanding falls apart when I start talking about testing void methods. This is where test doubles of some sort come in, and I swear, I've seen more blank stares when I explain this than I have any other time in the rest of my 42 years.
So I did something about it this class.
I took my own advice.
The change
Instead of having a big jump from TDD on a single class to this whole-hog example, I put in a couple of smaller examples, with exercises, between the two existing endpoints. In the first one, I introduce a test double that allows them to test that the side-effect of calling a method happens correctly. It takes a single interface and a single stub to implement this new concept, and they get it! Then I introduce another stub that provides data into the class under test, which requires another interface and stub class. And they still get it! Now we're at the point where we'd be previously, but I don't see any blank stares. Victory!
The lesson
If a test is hard to write, then you've probably bitten off more than you can chew. Comment it out and try a smaller byte.
That advice works for the instructor, too!
-- bab
I'm looking for a tool of some sort that will allow me to manage all the different projects that I have going on. I currently have about 10 different efforts in which I'm involved, each of which has its own context and state. I find myself switching between these projects all the time, and it is difficult to keep each one's current state in my head.
Do you use a tool to let you manage things like this? Specifically, I'm looking for something that would let me track my progress through a project, keep track of emails sent and received in some way, identify what the current state of a project is, what deliverables I ha