Friday, August 17, 2007

Pending scenarios in Behave#

When first authoring stories and scenarios in Behave#, the implementation to support the scenario probably doesn't exist yet.  Part 4 of Nelson Montalvo's series of posts on Behave# illustrates this quite nicely.  The problem is that you don't really want test failures because you haven't implemented a scenario yet.  Rbehave has the ability to create "pending" scenarios, which won't fail if the implementation doesn't exist.

Misleading failures

For example, here's a scenario that doesn't have an implementation yet:

[Test]
public void Withdraw_from_savings_account_pending()
{

    Account savings = null;
    Account cash = null;

    Story transferStory = new Story("Transfer to cash account");

    transferStory
        .AsA("savings account holder")
        .IWant("to transfer money from my savings account")
        .SoThat("I can get cash easily from an ATM");

    transferStory
        .WithScenario("Savings account is in credit")

            .Given("my savings account balance is", -20)
                .And("my cash account balance is", 10)
            .When("I transfer to cash account", 20)
            .Then("my savings account balance should be", -20)
                .And("my cash account balance should be", 10);
}

When I execute this story, I get a failed test and a misleading exception: 

Story: Transfer to cash account

Narrative:
	As a savings account holder
	I want to transfer money from my savings account
	So that I can get cash easily from an ATM

	Scenario 1: Savings account is in credit
TestCase 'BehaveSharp.Specs.AccountSpecs.Withdraw_from_savings_account_pending'
failed: BehaveSharp.ActionMissingException : Action missing for action 'my savings account balance is'.
	C:\dev\BehaveSharp\trunk\src\BehaveSharp.Examples\AccountSpecs.cs(70,0): at BehaveSharp.Specs.AccountSpecs.Withdraw_from_savings_account_pending()

 Not a very helpful message, especially if I'm executing a suite of stories and scenarios.

Pending scenarios

If a scenario has a pending implementation, I can now add a "pending" message to the scenario, so that I don't get any error messages:

[Test]
public void Withdraw_from_savings_account_pending()
{

    Account savings = null;
    Account cash = null;

    Story transferStory = new Story("Transfer to cash account");

    transferStory
        .AsA("savings account holder")
        .IWant("to transfer money from my savings account")
        .SoThat("I can get cash easily from an ATM");

    transferStory
        .WithScenario("Savings account is in credit")
            .Pending("ability to withdraw from accounts")

            .Given("my savings account balance is", -20)
                .And("my cash account balance is", 10)
            .When("I transfer to cash account", 20)
            .Then("my savings account balance should be", -20)
                .And("my cash account balance should be", 10);
}

Note the "Pending" method call after "WithScenario".  Think of "Pending" similar to the "Ignore" attribute in NUnit.  The story is there, the scenario is written, but the code to support the scenario doesn't exist yet.  Here's the output of the execution with "Pending":

Story: Transfer to cash account

Narrative:
	As a savings account holder
	I want to transfer money from my savings account
	So that I can get cash easily from an ATM

	Scenario 1: Savings account is in credit
		Pending: ability to withdraw from accounts

The scenario stops execution of the scenario (just so you can see the pending scenarios more easily), and outputs the pending message.  Without the "Pending" message, you will get an exception and your test will fail.  With "Pending", you can flag your pending scenarios without worrying about breaking the build if you check in.

No comments: