Simple Pattern for Arrange-Act-Assert style of Tests

Came up with a nice little pattern to implement Arrange-Act-Assert (AAA) style of tests using Visual Studio’s MSTest last night. The pattern is ridiculously simple and can be very useful for writing outside-in style of tests (some time referred to as acceptance tests too). By outside-in tests I am referring to those high-level tests which are meant to test, from top to bottom, a slice of business functionality.

At the heart of this simple pattern is an abstract base class which forces the concrete test classes to follow the AAA. This base class declares abstract signatures for Arrange(), Act() and Assert() methods and requires all the concrete classes to implement them.

protected abstract void Arrange();
protected abstract void Act();
protected abstract void Assert();

Hence, any class that implements this base class will have to implement the following

Arrange – which will allows them to setup the test data,
Act – the action that is being tested, and
Assert – check the output of the action for correctness.

The base will also have a method called Run(), which would call the Arrange(), Act() and Assert() in right sequence. This is the actual TestMethod which the “Test framework” will run.


[TestMethod]
public void Run()
{
Arrange();
Act();
Assert();
}

Here is what our base Test-Class would look like,

public abstract class BaseTest
{
[TestMethod]
public void Run()
{
Arrange();
Act();
Assert();
}
protected abstract void Arrange();
protected abstract void Act();
protected abstract void Assert();
}

And a concrete implementation would look something like this,

[TestClass]
public class When_Customer_Buys_an_items : BaseTest
{
private Cart _cart;
private Bill _bill;
private Receipt _receipt;
protected override void Arrange()
{
_cart = new Cart();
_cart.AddItem("Book", 12.49M, ProductType.Exempted, 1);
_cart.AddItem("music CD", 14.99M, ProductType.General, 1);
_cart.AddItem("chocolate", 0.85M, ProductType.Exempted, 1);
}
protected override void Act()
{
_bill = new Bill(_cart);
_receipt = _bill.GenerateReceipt();
}
protected override void Assert()
{
Testing.Assert.AreEqual(_receipt.Items.Count(), 3);
AssertUtil.AssertLineItems(_receipt, _cart);
Testing.Assert.AreEqual(_receipt.SalesTax, 1.50M);
Testing.Assert.AreEqual(_receipt.Total, 29.83M);
}
}

The neat thing about this pattern is the fact that all that the actual test classes need to be concerned about or be responsible for would be arranging the data, acting on this data and asserting the results. The base class will take care of the rest.

Try this out in your project; you would be pleasantly surprised with the structure and discipline this simple pattern brings to the way you write your tests.

Advertisements