May 2009 Entries
Automocking and BDD style tests with NUnit

I’m currently using context/specification style tests. While I think frameworks like J.P.Boodhoo’s are beautiful, I prefer something that works with ReSharper, TD.NET and CI without extra hurdles. I also want something my team, with limited exposure to *Unit frameworks, can easily pick up.

I’d prefer not to have the ceremony and misleading terminology of “Test” attributes, but its a trade-off I’m willing to make to more easily to integrate with team members and third party tools.

I put my testing stack along with an example test/spec project on github under the project name Specish.

About my tests/specs:

  1. resharper_navigationI preface every test fixture with the name of the class I’m testing. This lets me type “PC” in the navigation window of ReSharper to get to a PatientController or any class that tests patient controller.
  2. Automocks allow me to change constructor signatures with no consequence, and let me only mock objects and methods necessary for setup or verification. I stole the base class for my tests from here.
  3. I usually only have one assert per test method.
  4. I use a modified version of SpecExtensions I saw Steve Harman use at Cleveland Day of .NET last year… so instead of Assert.IsTrue(true) I write the more readable true.ShouldBeTrue();
  5. Custom ReSharper live templates for test fixtures and methods speed things up considerably.

The result looks something like this:

    [TestFixture] 
public class PatientController_when_searching_for_patients_returns_one_result : base_automock_test
{
ViewResult result;
IList<Patient> patients = new List<Patient>();

public override void establish_context()
{
patients.Add(new Patient{Id = 2});

Mock<IPatientService>()
.Setup(ps => ps.Search(It.IsAny<string>(), It.IsAny<string>()))
.Returns(patients);
}

public override void because()
{
result = Create<PatientController>().List("Joey", "Smith");
}

[Test]
public void it_returns_just_one_patient()
{
(result.ViewData.Model as Patient).ShouldEqual(patients[0]);
}

[Test]
public void it_returns_the_detail_view()
{
result.ViewName.ShouldEqual("Details");
}
}

And it shows up in the test runner as

PatientController when searching for patients returns one result

* it returns just one patient

* it returns the detail view

 

The test runner results document exactly how my controller behaves in this context.

PatientController returns just one patient and a detail view because I call List() on a PatientController in the context (search the returns one result) set in establish_context.

kick it on DotNetKicks.com

NHibernate and jQuery slides and code from Chicago Code Camp

Here’re the code and slides from my talks on NHibernate and jQuery.

And some links mentioned during my talks:

NHibernate:

jQuery:

Converting HQL to NHibernate LINQ

 

I was playing around with converting some HQL and Criteria queries to LINQ, and the result is pretty slick:

All I had to do was reference NHibernate.Linq and I went from:
 
        public IList<Stay> GetCurrentStays()
        {                       
            string hql = @"FROM Stay WHERE CheckinDate <= :now 
                    AND (CheckoutDate IS NULL OR CheckoutDate >= :now)";

            var query = getQuery(hql);
            query.SetDateTime("now", DateTime.Now);
            return query.List<Stay>();
        }
to:     
        public IList<Stay> GetCurrentStays()
        {
            var query = from stay in session.Linq<Stay>()
                        where stay.CheckinDate <= DateTime.Now &&
                              stay.CheckoutDate >= DateTime.Now
                        select stay;
            return query.ToList();
        }    
 
 
 
Goodbye Magic Strings.  Goodbye having to teach my team a another esoteric API and syntax.
Speaking at Chicago Code Camp – May 30th


This Saturday I’ll be speaking at Chicago Code Camp which to my initial dismay is not actually in Chicago but an hour or so north.  This is probably best since I’ll feel less nerdy for talking about technology all weekend instead of checking out the city.

I’ll be giving two presentation:

  jQuery Magic

  Get Rolling with NHibernate

If you haven’t signed up yet, there’s still time!

Creating software in two days: GiveCamp Retrospective Part 1

 

At Lansing GiveCamp I was chosen to lead a team tasked with creating a guest registration system for Ronald McDonald House of Mid-Michigan.  Ronald McDonald House wanted to get off their current system, paper, to streamline their processes and report on their data.  The event started around 7:00PM on Friday and ended with 3:00PM on Sunday.  That’s 44 hours.

At first it seemed too simple and I wondered if Microsoft Access wouldn’t have been sufficient for their needs.  That is until Jay Harris met with the client/charity and hammered out the Business Requirements.  Whew, there were a lot.

photo by Dave GiardFriday night came and we start the project.   First, we defined the domain entities.    We had no time to lose so with the domain defined Jay started creating business entity classes while I talked with Dave Giard and Eric Vogel more about the system architecture.

With the business entities ready and three developers wanting to get started at once, how do we get everyone productive?  There’s no database, no DAL…  This is where Inversion of Control paid out nicely.  I whipped up some fakes to return some hard-coded objects so the team could consume those until the actual database was ready. 

    public class FakeStaffMemberService : IStaffMemberService {

        private List<StaffMember> staffMembers = new List<StaffMember>() {
            new StaffMember() {Id=1, UserName="JSmith", FirstName="John", LastName="Smith",  
                Type=StaffType.Admin},     
        // ...
     
        public IList<StaffMember> GetAll() {return _staffMembers; }
        
        // ...
 

Then I told our IoC Container, StructureMap, to return a FakeStaffMemberService whenever an IStaffMemberService was requested. And yes, with proper Inversion of Control and TDD, it doesn’t matter that the database doesn’t exist in your controllers and middle-tier classes, but we had a lot of views and JavaScript to get written so it was important to hit F5 and see our website.

For the Data Access Layer, I grabbed Fluent NHibernate and fumbled getting automapping to do what I wanted.  It was one of those situations where I couldn’t tell if I was five minutes or five hours away from getting the thing to work... so I tossed it and went with normal Fluent NHibernate mappings.  It was somewhat tedious but a predictable and manageable task.  With a greenfield database, Fluent NHibernate is perfect.  Were we dealt existing schema, I would’ve feared a situation arising I couldn’t map with Fluent, but this wasn’t an issue here.   Fluent NHibernate makes the mappings strongly typed and trivial/beautiful while providing helpers for testing your mappings.  Along with that, I created a “test”, set to run explicitly, to create the schema and populate the database.  This let us never need to open SQL Server or even think about its existence.   In order to persist a new property, we simply had to add it to the mapping and add a line in our integration test for verification.  This led to a less than ideal schema but functioning software was our concern.  Later, when the dust settled and product was delivered, Eric and I wrote a script to optimize the schema.

n1053319431_408708_8085625[1] This infrastructure allowed us to just rip through code all day Saturday… which was good because we were hindered by multiple power outages, a restocking trip required by myself to replace clothes and toiletries stolen from my car the night before and some fumbling trying to figure out an ASP.NET MVC binder solution.

With an hour and a half to go to our demo, I realized I had well over two hours of work to do.  The main feature of our application, recording a patient’s support people and their stays was not going to be complete.  I still had to code the binder and the JavaScript to handle multiple support people.   I was sure trying to explain what I needed to someone would be insufficient for them to comprehend and return what I wanted.  I started plowing through it, hoping maybe I could come in under the wire when I saw an out.  I knew what the Act and Assert was in my Unit Test.  I wrote them, checked it in and asked Dennis Burton for an hour of his time to fill out the Arrange part of the test along with the implementation.  There were three failing tests and I needed them all to be green. He downloaded the project and because of our use of Inversion of Control he did not need to set up the database or know anything about the rest of the domain.  An hour later he checked in the code and because all of the tests passed I didn’t even care about looking at his implementation.  Dropping it into the project was the missing piece and we were done with about fifteen minutes to spare.

In this part I talked about what went right.   In Part 2 I’ll talk about what didn’t.

(First photo by David Giard)