Unit test patterns, Episode I : A foundation emerges

Learning TDD has been a lot of work. I’ll start by saying that. If you’re new to TDD, you’re probably floundering around a bit. I did. A lot. I think the main, underlying issue is to “see the layers,” specifically just the one layer you’re writing a test for. Before TDD, I saw an application as more of a big unit with a few large layers. This really causes a struggle when writing a test. TDD really pressures you (drives you ;-)) to see the small, incremental steps. It’s seeing those little steps that’s the trick. If you bite off too much of an application to unit test because you’re a power coder that “get’s things done,” then writing that test becomes like trying to put your shoes on without untying them. It will frustrate you to no end. I’ve been there and done that.  But don’t get rid of the laces. Just untie the shoes. This is what kept me from giving up on TDD– something about it just felt right and smarter folks than me were doing it. Now, I’m no lemming, blindly following all the latest fads, but, well, I’m no lemming blindly following the status quo either. And to be fair, TDD is far too old to be a fad.

And I’m certainly still learning– I’m young to TDD– just barely over a year old now. I had tried it a few times before and couldn’t quite get off the ground, so I took a weekend at home and locked myself in a room until I wrote some successful tests. That’s when I finally got started and I’ve used it on my most recent project at work: a new website (ASP.Net MVC). Perhaps someday I’ll write about how to start a project with TDD, but for now I just want to share a few testing patterns I’m currently using. Feel free to critique; I’m on a journey– “Give instruction to a wise man, and he will be still wiser; Teach a just man, and he will increase in learning.”

So, about those patterns. This post will look at the basic one which is all about

  • a process
  • a situation
  • and expectations

This fits well with Arrange, Act, and Assert for the mechanics of the tests/specs, and all the formats share this overarching design or structure which ends up looking like this

namespace Process
{
   public class Situation
   {
      public void Expectation()
      {}
   }
}

I like the BDD naming convention and totally favor a perspective of “specifying behavior” rather than “passing tests.” In the past, I’ve used “When” to declare the process and “Given” to declare the situation. Because of this, I typically reorder the classic “Given-When-Then” naming pattern to “When-Given-Then.”

I’ll take a recent real world (and common) situation for an example: a web site where a user who has an account may invite others to join that account. I’ll call this a UserInvitationManager (for this post).

I feel using the “When” first to declare the activity/process establishes the context quickly. So…

namespace When_inviting_a_user_to_join_an_account
{
}

The situation is limited to just the input parameters in this case, so…

namespace When_inviting_a_user_to_join_an_account
{
   [TestFixture]
   public class Given_an_email_address_and_an_account_number
   {
   }
}

Before I move on to the “Then,” I set up for those Thens. This can be most of the work, actually, as you’ll see. Most of the time, I put the Act(ing) into the TestFixtureSetup method rather than inside the Test method. I do this so that each TestFixture specifies the behavior for one situation and has the chance to easily Assert many things after the single Act(ion). By no means am I married to this. If a situation serves me better to re-Act before every Assert(ion), I’ll do it in an instant. But otherwise, I’ll Act once, which keeps the Assert(ion)s very simple.

So to set up, I first need to define and initialize the actors involved, including the system under test, or in other words, the process for which I’m specifying behavior. And like I said, I’m skipping some of the “TDD-how-to,” so I won’t go into how I came up with the dependencies for the UserInvitationManager. But I will go ahead and Act at the end of the setup.

namespace When_inviting_a_user_to_join_an_account
{
   [TestFixture]
   public class Given_an_email_address_and_an_account_number
   {
      UserInvitationManager invitationMgr;
      IUserInvitationSender invitationSender;
      IAccountManager accountMgr;

      String emailAddress;
      String accountNumber;

      [TestFixtureSetup]
      public void SetupTestFixture()
      {
         // Arrange
         invitationSender = MockRepository.GenerateMock<IUserInvitationSender>();
         accountMgr = MockRepository.GenerateMock<IAccountManager>();
         invitationMgr = new UserInvitationManager(invitationSender, accountMgr);
         emailAddress = "newUserEmail@doesntmatter.stilldoesntmatter";
         accountNumber = "doesntMatterEither";

         //Act
         invitationMgr.InviteUser(emailAddress, accountNumber);
      }
   }
}

So, a lot of code, relatively speaking, just got added. For me, arranging is defining your parties and intializing them.

I generally define four groups of parties:

  • system under test (the UserInvitationManager)
  • dependencies (the invitationSender and accountMgr)
  • parameters (the emailAddress and accountNumber)
  • result (this action returned no result, but if it did, I would have set the result variable during the Act)

Then I initialize them.

To keep things separated in the above example, I initialized them in the setup method, but most times I initialize what I can on definition to reduce unnecessary loc.

IAccountManager accountMgr = MockRepository.GenerateMock();

Purely a preference. Perhaps a TDD puritan would refuse, but once I got used to this format, I didn’t need to always separate the definition and intialization, and I found that it cleans up some stuff for other setup efforts, like stubbing dependencies.

Now we get to the “Thens.” And, thanks to Ayende and RhinoMocks, they’re short and sweet, as, I think, they should be. Also notice one Assert per Test. Yeah, I’m generally one of those.

namespace When_inviting_a_user_to_join_an_account
{
   [TestFixture]
   public class Given_an_email_address_and_an_account_number
   {
      UserInvitationManager invitationMgr;
      IUserInvitationSender invitationSender;
      IAccountManager accountMgr;

      String emailAddress;
      String accountNumber;

      [TestFixtureSetup]
      public void SetupTestFixture()
      {
         // Arrange
         invitationSender = MockRepository.GenerateMock<IUserInvitationSender>();
         accountMgr = MockRepository.GenerateMock<IAccountManager>();
         invitationMgr = new UserInvitationManager(invitationSender, accountMgr);
         emailAddress = "newUserEmail@doesntmatter.stilldoesntmatter";
         accountNumber = "doesntMatterEither";

         //Act
         invitationMgr.InviteUser(emailAddress, accountNumber);
      }

      [Test]
      public void Then_the_user_invitation_manager_should_pre_register_that_email_address_to_the_account()
      {
         accountMgr.AssertWasCalled(acctMgr => acctMgr.PreRegisterByEmailAddress(accountNumber, emailAddress));
      }

      [Test]
      public void Then_the_user_invitation_manager_should_send_an_invitation_to_the_given_email_address()
      {
         invitationSender.AssertWasCalled(sender => sender.SendInvitation(emailAddress));
      }
   }
}

Pretty basic, but again:

  • One [TestFixture] per situation as generally defined (“Given”) by parameters. Sometimes, the situation is additionally defined by a result from calling a dependency.
  • Usually one Act(ion) per situation. Sometimes this is not possible or preferable, and when it’s not, I don’t cry about it.
  • One Assert(ion) per [Test] method.

That’s the foundational pattern that has emerged for me and it’s good for many of my specifications. In a future post, I’ll actually change up how I name some of these elements, like the Whens and the Thens and even the system under test. See the previous post for a hint. But upon this basic structure I can easily define more complex situations. So, it’s been a little over a year for TDD/BDD and me, and this is where I am…headed.

Now read Unit test patterns, Episode II : Inheritance strikes back.

Advertisements

3 Responses to Unit test patterns, Episode I : A foundation emerges

  1. Pingback: Unit test formats, Episode 2 : Inheritance strikes back « FullRewrite

  2. Pingback: Unit test patterns, Episode III : Avoid the combinatorial – cheat! « FullRewrite

  3. JC says:

    Someone finally explains in extremely clear words what DI, IOC and TDD are all about. Thank you for detailing the logic that brought you to the solution, I really think all you say here makes a lot of sense and I feel I’ve really learnt something today.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: