Top 10 Movie List — just for fun

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

New .Net testing framework, xUnit.net, available on CodePlex

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

Episode 2 – The InputReader and the start of the Processor

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

Interesting difference using nested test suites in JUnit versus NUnit

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

Episode 1 of Deep Dive Revisited — Setting the stage with customer tests

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