February 6, 2010

Fitnesse Test Styling

In my previous post, I concentrated on setting up Fitnesse. Unfortunately, I did a lot of hand-waving when it came to the test used in the example. I got called out on it, and rightfully so.

Gregor said…

Are you really hard coding the prices and the name of the product into the method names? Do you also have methods named "The_sub_total_shows_3_49" and The_sub_total_shows_8_17"? This means that you cannot change your acceptance test without renaming or adding methods in the fixture. This surely is not the purpose of FitNesse.

The test wasn’t the purpose of the post, and I should probably have Lorem ipsum’d it. Alternatively, I could have explained myself a little better, and improved the test.

My response to the comment is, “Sincerely, thank you for your comments, and yes, yes, true, and sure it is.” The real problem to my point of view is that the product owner, subject-matter expert, customer, stakeholder, or whatever you have probably explained to the programmer (me) something like this:

The customer purchases items. Those items are scanned. The price of the item is put on the bill along with it's description. See figure 1. The subtotal is calculated as the sum of the price of all items on the bill and displayed at the bottom.

I immediately translated this in real time into an implementation. That of a bill, of descriptions showing up on receipts, and prices being displayed and tallied. I broke up the statement into easily re-useable and parameterized chunks. In traditional Fit/Fitnesse tests this probably could have been efficiently captured in a traditional ColumnFixture and look something like:

col-fixture-total-items

The corresponding fixture implementation could then be given as

  public class TotalItemsPurchased : fit.ColumnFixture
  {

    private Bill _bill;

    public TotalItemsPurchased ()
      {
        _bill = new Bill();
      }

    public string Sku
    {
      get
      {
        return _bill.LastItem.Sku;
      }
      set 
      {
        _bill.Scan(value);
      }
    }

    public string Subtotal()
    {
      return _bill.SubTotal.ToString("C");
    }

    public string Description()
    {
      return _bill.LastItem.Description;
    }

    public string Price()
    {
      return _bill.LastItem.Price.ToString("C");
    }
  }

Where Bill is the system under test (or it is for this example anyway). There is nothing wrong with this. It’s a very clean, clear, and concise way to implement these requirements, and to Gregor’s point the implementation code isn’t so weird anymore.

For me though, writing acceptance tests like this becomes too much like programming. I’m moving towards making my acceptance tests read more like end-user documentation. I’d rather the acceptance tests be in the words of the customer. I’m even willing to threaten to publish the acceptance tests as the end-user documentation.

A better example of flow mode using plain-text tables would have been to take the actual words of the customer and make them directly executable.

total-items-end-user

The Fitnesse code for this test looks like:

![ TotalItemsPurchased
The customer purchases items. 
Those items are scanned. 
The price of the item is put on the bill along with it's description. See figure 1. 
The subtotal is calculated as the sum of the price of all items on the bill 
and displayed at the bottom.
]!

 

However, the underlying fixture looks weird again (e.g., The_price_of_the_item_is_put_on_the_bill_along_with_it_s_description_See_figure_1. Honestly I'm ok with that. I can accept the role of the fixture as the bridge between the wiki and the test automation if it means the author of the test can freely communicate the intent of the feature in his/her own words. The automation code itself is free to be separate from the fixture code in this regard.

As far as parameterizing the tests, for the purpose of making the fixture code more re-useable and programmer friendly, that’s ok, if that’s what you’re into, and as my commenter points out Fitnesse gives you more than a few choices (e.g., ScenarioTable, ScriptTable, ActionFixture, DoFixture, et. al.).

In fact, you can parameterize a statement like, “The description of the item is “Bubbly Yummy” and costs “$0.79” in flow-mode and a plain-text table like this:

![" TotalItemsPurchased
  The description of the item is "Bubbly Yummy" and costs "$0.79"
]!

This can be implemented in a fixture like this:

  public class TotalItemsPurchased
  {
    public bool The_description_of_the_item_is_and_costs(string description, string cost)
    {
      // Fire up the API and do some testing
    }
  }

It still looks a little weird, but it avoids hard-coding the values in the function names.

My personal goal with acceptance tests is to get the acceptance tests to feed a TDD cycle. In the standard red-green-refactor cycle is where I’ll worry about the code structure of the test infrastructure and the the application. I want to follow the cycle as depicted in Growing Object-Oriented Software, Guided by Tests:

test-cycle

I don’t want to pressure the writing of the acceptance criteria with implementation concerns. As a result, having fixtures that are mere connectors between the implementation and acceptance criteria is palatable in my book. I’m digging flow-mode style Fitnesse tests because there is a lot of freedom afforded the author of the acceptance test.

No comments:

Post a Comment