Sunday, March 6, 2011

Solving the supermarket coding kata using TDD – Part 1

The supermarket coding kata problem domain deals with the scenario of pricing goods at supermarkets. The scenario handles situations like.
Items in supermarket have simple prices, e.g. One Gatorade for $4.5. Other items may have complex prices like three for dollar or $3 for one pound etc.
I have tried to solve the kata using TDD and have recorded the session while attempting to address the situation.

Implementing the Item class

Below are the steps from the TDD session addressing the supermarket coding kata sample:
1.       Create a new visual studio solution and add a test project to it. I have named the project as SupermarketKata.Model.Tests. Add another class library to the solution and name it SupermarketKata.Model.
2.       Add a new unit test to the test project and name it Items_Fixture. This class will contain the test methods for the Item object.
3.       The first test we will be writing on the Item_Fixture will be checking whether every item has a name associated with it. The below test code is used to check this functionality.
[TestClass]
public class Item_Fixture
{
    [TestMethod]
    public void items_should_have_a_name_associated_to_it()
    {
        Item item = new Item("Apple juice 2Ltr");
        Assert.AreEqual<string>(item.GetName(), "Apple juice 2Ltr");
    }   
}

4.       After adding the code to the test method, I have used the Refactor menu item, “Generate new type” to generate the Item class. Similarly the constructor and GetName method is generated using refactoring.
5.       Run the test case and you can see the test case will fail as there is no implementation in the GetName method.
6.       Add the code required to the Item class to make this test pass.
public class Item
{
    public Item(string itemName)
    {
        _name = itemName;
    }

    public string GetName()
    {
        return this._name;
    }
       
    string _name;

}

7.       Run the test again and now you can see it pass.
8.       Next I have used the same approach given above to create the test case for checking whether every item has a unique item number.
[TestMethod]
public void items_should_have_a_unique_itemnumber()
{
    Item item = new Item("Apple juice 2Ltr");
    Item item2 = new Item("Apple juice 1Ltr");

    Assert.IsFalse(item.GetItemNumber() == item2.GetItemNumber());
}

Code change in the Item class
public class Item
{
    public Item(string itemName)
    {
        _name = itemName;
        GenerateItemNumber();
    }

    private void GenerateItemNumber()
    {
        _itemNumber = Guid.NewGuid().ToString("N");
    }

    public string GetName()
    {
        return this._name;
    }

    public string GetItemNumber()
    {
        return _itemNumber;
    }
       
    string _name;
    string _itemNumber;

}

9.       The last test on the item class is to check whether the Total cost of the item is calculated based on the pricing strategy. For this I have mocked the pricing strategy used for calculating the price based on the situation as I haven’t implemented the class yet.
[TestMethod]
public void items_have_a_pricingstrategy_which_is_used_to_calculate_the_unit_price_based_on_pricingstrategy()
{
    var mockedPricingStrategy = new Mock<PricingStrategy>();
    mockedPricingStrategy.Setup((x) => x.GetUnitPrice()).Returns(9M);

    Item item = new Item("Apple juice 2Ltr");
    item.SetPricingStrategy(mockedPricingStrategy.Object);

    decimal price = item.GetPrice();
    Assert.AreEqual<decimal>(9M, price);
}

10.   Use the refactoring tool to generate the GetPrice and SetPricingStrategy method on the item class. The final implementation looks like
public class Item
{
    public Item(string itemName)
    {
        _name = itemName;
        GenerateItemNumber();
    }

    private void GenerateItemNumber()
    {
        _itemNumber = Guid.NewGuid().ToString("N");
    }
       
    string _name;
    string _itemNumber;
    PricingStrategy _pricingStrategy;

    public string GetName()
    {
        return this._name;
    }

    public string GetItemNumber()
    {
        return _itemNumber;
    }

    public void SetPricingStrategy(PricingStrategy pricingStrategy)
    {
        _pricingStrategy = pricingStrategy;
    }

    public decimal GetPrice()
    {
        return _pricingStrategy.GetUnitPrice();
    }
}

Next we’ll look into the implementation of the pricing strategies and continue our TDD session.

No comments: