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

Automated Deployment with TFS

One of the few things that can add true agility to the Agile practices that you claim to do is Automation. – “AUTOMATE EVERYTHING YOU CAN!

In my current project we have successfully automated our application deployment process. To us, deploying the ‘latest’ or an ‘already compiled revision’ of the build to the desired environment (Integration/QA/UAT/Prod etc) is just a click away. This encourages the team to deploy quickly, frequently and fearlessly.

This post will have us take a look at how to automate your application deployment using Microsoft Team Foundation Server (TFS). I am assuming that you are familiar with TFS and Team builds. Needless to say that you should have a Build Server (Build Controller, Agents) up and running. We will extend CI build capabilities of TFS to deploy our builds continuously to the integration environment. Assuming that you have the Build Controller and Agents in place, the first thing we might want to do is setup a basic CI build on the Build Server, selecting Continuous Integration as the build trigger. This will setup our out-of-the box CI Build Service using TFS.

The CI build definition we created is good enough to compile builds, run tests, deploy databases (if configured) and drop the builds to a specified location every time we check-in code. But what we want to do here is extend this build definition in a manner that in addition to doing all of the above; it will also go ahead and deploy the application on the web server.

Here is how we do it,

1.     Right click on the CI build-definition in team explorer.

2.     Select “Process”

3.     Expand “Advance” node, if not already expanded

4.     In the ‘MSBuild Arguments’, provide the following parameters,

/p:DeployOnBuild=True
/p:DeployTarget=MsDeployPublish
/p:CreatePackageOnPublish=False
/p:MSDeployPublishMethod=RemoteAgent
/p:AllowUntrustedCertificate=True
/p:MSDeployServiceUrl=<name of the Server>
/p:DeployIisAppPath=<IIS App>/<Virtual Dir>”
/p:UserName=<username>
/p:Password=<password>

And, there you go – simple, yet powerful. Try it out in your projects; you might be pleasantly surprised with the results.

Any discussion about Agile and Build Automation is not complete it without a mention of Continuous Deployment and Continuous Delivery. Continuous Deployment is about shipping out every feature developed by the team through the Deployment Pipeline all the way to the production in an automated fashion. Continuous Delivery is having a human intervention somewhere in the Deployment Pipeline to before making the feature available to the users.

These techniques are really about taking your agile practices to the extremes, both in terms of potential and performance. But, even if you don’t intend to get there immediately, it would still be unthinkable as to why wouldn’t you start automating things that you need to be doing as often as needed and as accurate as possible – Build Deployment definitely being one of them.

Story about User Stories

It’s amazing how people somehow manage to figure out ways to abuse systems that they once so passionately fought to bring in. I recently came across a user story card which had the whole sequence diagram scribbled on it in an extremely small fonts. Interesting work-around, isn’t it? For those who have not seen one, a user story card is typically a 3×5 index card used by many organizations to represent a user story.  The small size has been selected for a reason. The idea behind having a 3×5 index card is to constraint the user story to short and simple.

But user story card is just a part of the story. Let us try look at the whole story itself. Please allow me to tell you the story of user stories.

A user story describes desired functionality from the business perspective; it is the user’s story. A good user story describes the desired functionality, who wants it, and how and why the functionality will be used. I completely agree with Mike Cohn’s favourite Template for writing user story which are short and simple,

As a [user role]

I want [functionality]

So that [reason]

 A user story is comprised of:

1. Card – the written description of the story, serves as and identification, reminder, and also helps in planning.

2. Conversation – this is the meat of the story; the dialogue that is carried out with the users; recorded notes; mockups; documents exchanged.

3. Confirmation – the acceptance test criteria that the user will utilize to confirm that the story is completed.

A very good guideline for writing good user stories is the INVEST model

Independent – One user story should be independent of another (as much as possible). Dependencies between stories make planning, prioritization, and estimation much more difficult. Often enough, dependencies can be reduced by either combining stories into one or by splitting the stories differently.

Negotiable – A user story is negotiable. The “Card” of the story is just a short description of the story which do not include details. The details are worked out during the “Conversation” phase. A “Card” with too much detail on it actually limits conversation with the customer.

Valuable – Each story has to be of value to the customer (either the user or the purchaser). One very good way of making stories valuable is to get the customer to write them. Once a customer realizes that a user story is not a contract and is negotiable, they will be much more comfortable writing stories.

Estimable – The developers need to be able to estimate (at a ballpark even) a user story to allow prioritization and planning of the story. Problems that can keep developers from estimating a story are: lack of domain knowledge (in which case there is a need for more Negotiation/Conversation); or if the story is too big (in which case the story needs to be broken down into smaller stories).

Small – A good story should be small in effort, typically representing no more, than 2-3 person weeks of effort. A story which is more than that in effort can have more errors associated with scoping and estimation.

Testable – A story needs to be testable for the “Confirmation” to take place. Remember, we do not develop what we cannot test. If you can’t test it then you will never know when you are done. An example of non-testable story: “software should be easy to use”.

So the moral of the story is this. User Stories being the cornerstones for Agile development, deserve their fair share of time, effort and most importantly prudence to be “invested” in them in order to lay a strong foundation for project.

Agile Software Development

When we first started using Agile, we were amazed by the sheer quickness with which we were able to respond to change-requests and issue-resolutions; we were amazed by the ease with which we could accomodate new requirements; and most of all we were amazed by the way we could focus on the grass-root level ‘real work’, keeping all the mumbo-jumbo around software development aside. It was all about being quick, aggressive and pragmatic as a team. In a very short period of time, I had become a big fan of Agile. I always found myself convinced that Agile would work, and till date my openion has not changed. Let’s examine some of the key differentiators of Agile methodology over conventional practices:

More often than not customers do not completely know what they actually want at the beginning of a project. Generally this is the time when the project contract is signed. Obviously, more often than not the development team ends up providing a solution which partially or not at all solves their problem (even if contract is met completely). This leads to a very high degree of dissatisfaction among the customers. Agile software development methodology answers the problem with a simple, common sense driven approach to software development. It allows the customer to have a direct visibility into the direction in which the project is heading. This allows them to correct and modify an existing requirement or even come up with a brand new one at any point of time in the project. The transparency that Agile provides results in a high level of confidence and satisfaction among the customers.
Agile is about embracing change. It encourages you to accommodate change at any point of time. It even welcomes the new one. These changes are then added to the wish-list (backlog). And the list is prioritized again with the help of customers.
Agile is about delivering continuous stream of value. It breaks down the task in small pieces of deliverable which can be accomplished in a short period of time, say a fortnight (this is called sprint). These task pieces are called backlog items. The list is then prioritized with the help of the customer. Small deliverables are released on a regular basis based on the backlog. The customers play with it and give their invaluable feedback.

Agile encourages not to plan too far ahead. Agile does not bother you about planning for too remote a future. It plans for one sprint at a time. This gives the customer small deliverables on a frequent basis to work and play with. This also ensures a frequent feedback from the customer.
“Business folks must get involved”, is the trick we missed out on in the conventional software development models, so to say. We did not get the customers involved enough. This resulted in the project floating like a boat without sail. Having regular input and feedback ensures that the team is on the right track. Important and critical features (decided by the customers) are built and tested first. It is also comforting for the customer because he or she has a clear visibility of where his or her investment is at any point of time.

Agile encourages regular Face-to-face communication. Agile understands the fact that most effective communication is, in fact, face-to-face communication. Hence it’s a practice that the team must meet at least for five minutes daily and discuss about what did they did yesterday and what they are planning to do today. It is also discussed if there is any impedance. This sort of meeting is called a scrum in the agile world.
Agile is designed for high degree of customer involvement, less up-front planning (as requirements evolve), and high degree of effective communication both within the team as well as with customers. Transparency and clear communication has resulted in an unprecedented level of customer.

I find this idea of Moving with the Cheese behind Agile extremely exiting, how about you?