Tag-Archive for ◊ BDD ◊

Wednesday, March 16th, 2011
The Business Rule coding Kata (Kata Sixteen) deals with a set of changing business rules with an example of writing an order processing application for a large company. The focus is on the payments and in particular on the processing required when a payment was received by the company. The Kata specifies a full set of rule snippets like:
  • · If the payment is for a physical product, generate a packing slip for shipping.
  • · If the payment is for a book, create a duplicate packing slip for the royalty department.
  • · If the payment is for a membership, activate that membership.
  • · If the payment is an upgrade to a membership, apply the upgrade.
  • · If the payment is for a membership or upgrade, e-mail the owner and inform them of the activation/upgrade.
  • · If the payment is for the video “Learning to Ski,” add a free “First Aid” video to the packing slip (the result of a court decision in 1997).
  • · If the payment is for a physical product or a book, generate a commission payment to the agent.
  • · and so on, and so on, for seven long, yellow pages.

We’ll try to solve these rule sets one by one and do this using BDD. I’ll be using the StoryQ framework for writing my BDD test cases.
Part 1: If the payment is for a physical product, generate a packing slip for shipping.
I have created my test case as given below.
[TestMethod]
public void PaymentForAPhysicalProductGeneratesAPackagingSlipForShippingTest()
{
new Story(“payment is for a physical product, generate a packing slip for shipping”)
.InOrderTo(“Ship products a packaging slip should be generated”)
.AsA(“User”)
.IWant(“Packaging slip for shipping my products”)
.WithScenario(“Payment for physical product”)
.Given(ProductIsReadyForPayment)
.When(PaymentIsDoneForProduct)
.Then(ShouldAlsoGenerateAShippingSlipForTheProduct)
.ExecuteWithReport(MethodBase.GetCurrentMethod());
}
Now to implement the Given, When, Then scenarios, I’ve use refactoring to generate the methods and variables. My test methods look like.
private void ShouldAlsoGenerateAShippingSlipForTheProduct()
{
_payment.CompletePayment(PaymentAmount);
_shippingServiceMock.Verify((x) => x.GenerateShippingSlipForAddress(_physicalProduct.GetShippingAddress()));
}
private void PaymentIsDoneForProduct()
{
_payment = new Payment(_physicalProduct, ShippingAddress);
_shippingServiceMock = new Mock<IShippingSlipService>();
_payment.SetShippingService(_shippingServiceMock.Object);
}
private void ProductIsReadyForPayment()
{
_physicalProduct = new Product(“Blackberry Storm”);
var physicalProduct = _physicalProduct;
const string shippingAddress = “iSense Bangalore”;
physicalProduct.SetShippingAddress(shippingAddress);
}
I have mocked the IShippingSlipService and set the expectations on the GenerateShippingSlipForAddress method on the service.
Code for the implementation
public class Product
{
private string _shippingAddress;
private string _name;
private readonly string _productCode;
public Product(string name)
{
this._name = name;
_productCode = Guid.NewGuid().ToString(“N”);
}
public void SetShippingAddress(string shippingAddress)
{
this._shippingAddress = shippingAddress;
}
public string GetShippingAddress()
{
return _shippingAddress;
}
public string GetProductCode()
{
return _productCode;
}
}
public class Payment
{
private readonly Product _physicalProduct;
private decimal _amount;
private IShippingSlipService _shippingSlipService;
private string _shippingAddress;
public Payment(Product physicalProduct, string shippingAddress)
{
if (physicalProduct == null) throw new ArgumentNullException(“physicalProduct”);
if (shippingAddress == null) throw new ArgumentNullException(“shippingAddress”);
this._physicalProduct = physicalProduct;
this._shippingAddress = shippingAddress;
}
public virtual void CompletePayment(decimal amount)
{
_amount = amount;
if (_physicalProduct != null) _shippingSlipService.GenerateShippingSlipForAddress(_physicalProduct.GetShippingAddress());
}
public void SetShippingService(IShippingSlipService shippingSlipService)
{
_shippingSlipService = shippingSlipService;
}
}
public interface IShippingSlipService
{
void GenerateShippingSlipForAddress(string shippingAddress);
}
Results
Kata16_1
Category: .Net, Agile/Scrum, Testing/QA | Tags:  | Leave a Comment
Sunday, March 13th, 2011
BDD is a higher level of unit testing by using terminology focused on the behavioral aspects of the system rather than testing, it creates better documentation of your system by recording its intent which makes your system easier to learn for new developers and relearn for when you revisit your code further down the line. BDD is a practice that has evolved out of established agile practices and is designed to make them more accessible and effective for teams new to agile software delivery. Over time, BDD has grown to encompass the wider picture of agile analysis and automated acceptance testing.
BDD lets you to write test in the concept of Given-when-then style. For e.g. a normal BDD test case looks like.
new Story(“Items can have unit price”)
.InOrderTo(“Supermarket can have items with unit prices”)
.AsA(“User”)
.IWant(“To idenify items with unit prices in the supermarket and get the prices from the checkout list”)
.WithScenario(“Items in supermarket will have unit prices”)
.Given(AnItemIsCreated)
.And(UnitPricingStrategyIsAssignedForTheItem)
.When(GetPriceMethodIsCalledOnTheItem)
.Then(ShouldReturnTheUnitPriceForTheItem)
.ExecuteWithReport(MethodBase.GetCurrentMethod());

This is as simple as converting a user story defined in a template like
· As a (X)
· I want to (Y)
· So that (Z) where Y is some feature, Z is the benefit or value of the feature, and X is the person (or role) that will benefit.
To
· Given (X)
· When (Y)
· Then (Z) where X is some given context, Y is the event or action occurred in the context and Z ensures some outcome.
Frameworks for BDD?
In this post we’ll see how to do BDD using the StoryQ framework. StoryQ is a portable (single dll), embedded BDD framework for .NET. It runs within your existing test runner and helps produce human-friendly test output (html or text). StoryQ’s fluent interface adds strong typing, intellisense and documentation to your BDD grammar. We’ll convert our sample for supermarket pricing coding kata to BDD test cases using the StoryQ framework.
The tests to check whether items have a name and unique number is written as
[TestMethod]
public void ItemTestMethod()
{
new Story(“Items in the supermarket should have a name”)
.InOrderTo(“Identity items at checkout”)
.AsA(“User”)
.IWant(“To identify the items in my checkoutlist”)
.WithScenario(“Adding items”)
.Given(ItemHasANameDefined)
.When(GetNameIsCalled)
.Then(ShouldReturnTheNameofTheItem)
.ExecuteWithReport(MethodBase.GetCurrentMethod());
}

[TestMethod]
public void ItemNumberTest()
{
new Story(“Items in the supermarket should have a unique number that is system generated”)
.InOrderTo(“Uniquely identify items in the supermarket”)
.AsA(“User”)
.IWant(“Uniquely identify items in the supermarket”)
.WithScenario(“Adding items”)
.Given(ItemIsCreated)
.When(GetItemNumberIsCalled)
.Then(ShouldReturnANumberThatIsAutogenerated)
.ExecuteWithReport(MethodBase.GetCurrentMethod());
}

Then the output of the testrunner will be a report generated as
StoryQ report
Monday, December 27th, 2010

Auto mocking allows you to get object of the type you want to test without setting up mocks by hand. Using an auto mocker you can create the mock classes with dependencies and the container will automatically resolve the dependencies for you. The auto mocker will also keep track of all the mocks it creates, and allows you to retrieve them if you need to stub a specific behavior. In this post we’ll se how to create an auto mocking container for Moq using Unity.

The container implementation mainly has 2 methods GetMock and Create.

The GetMock is used to get the MocK of the object so that you can setup expectations and behaviours and later use this for verification.

public Mock<T> GetMock<T>(params object[] constructorParameters) where T : class

{

var _mockedObject = (IMocked<T>)this.Create<T>(constructorParameters);

return _mockedObject.Mock;

}

The Mock method is responsible for creating the mock and resolving dependencies

public T Create<T>(params object[] constructorParameters) where T : class

{

if (!_container.IsRegistered<T>())

{

var mockedType = new Mock<T>(constructorParameters).Object;

var resolvedType = _container.BuildUp<T>(mockedType);

Register<T>(resolvedType);

}

return _container.Resolve<T>();

}

Test methods

Customer customer = CreateMockCustomerWithOrder();

var orderRepository = _mockContainer.GetMock<IOrderRepository>()

.Setup(o => o.GetByCustomer(customer)).Returns(customer.Orders);

_mockContainer.Register<IOrderRepository>(_mockContainer.Create<IOrderRepository>());

ICustomerRepository customerRepository = _mockContainer.Create<CustomerRepository>();

customerRepository.Add(customer)

The UnityMockContainer code used in this sample.

public class UnityMockContainer

{

IUnityContainer _container;

public UnityMockContainer()

{

_container = new UnityContainer();

}

public Mock<T> GetMock<T>(params object[] constructorParameters) where T : class

{

var _mockedObject = (IMocked<T>)this.Create<T>(constructorParameters);

return _mockedObject.Mock;

}

public T Create<T>(params object[] constructorParameters) where T : class

{

if (!_container.IsRegistered<T>())

{

var mockedType = new Mock<T>(constructorParameters).Object;

var resolvedType = _container.BuildUp<T>(mockedType);

Register<T>(resolvedType);

}

return _container.Resolve<T>();

}

public T Create<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class

{

if (!_container.IsRegistered<T>())

{

var mockedType = Moq.Mock.Of<T>(expression);

var resolvedType = _container.BuildUp<T>(mockedType);

Register<T>(resolvedType);

}

return _container.Resolve<T>();

}

public void Register<TFrom, TTo>() where TTo : TFrom

{

_container.RegisterType<TFrom, TTo>();

}

public T Resolve<T>()

{

return _container.Resolve<T>();

}

public void Register<TFrom>(TFrom instance)

{

_container.RegisterInstance<TFrom>(instance);

}

}