Carlo V. Dango
Carlo V. Dango

Reputation: 13882

Optional parameters with Specflow

How do I best handle the fact that many of my steps should take 0, 1 or even 2 dates as "first parameters"? Eg, how do I best make support for optional arguments in Specflow

The easiest case is when dates are of no concern as long as the steps happen after each other

 Given Peter was born 23-06-1973
 And Peter created an account
 And Peter deposited $200

Often though, a lot of steps that are time-dependent, such as

 Given Peter was born 23-06-1973
 And at 1-4-2012 Peter created an account
 And at 13-4-2012 Peter deposited $200

At other times there are two dates such as the real-time date and the date when something had happened. Eg. Peter filled out a printed form 14-4-2012 for a money transfer, but the form got lost for a few days, and we need to record today that the form was filled out a few days ago.

 Given Peter was born 23-06-1973
 ...
 And at 16-4-2012 really at 14-4-2012 Completed a transfer form to transfer $100 to account 12345 

Upvotes: 10

Views: 12477

Answers (3)

Alex KeySmith
Alex KeySmith

Reputation: 17101

This worked well for me, overloading the functions that require optional parameters and passing in defaults.

It would be great if specflow supported optional parameters e.g. string searchTerm = "" but it doesn't at the moment.

[When(@"I request a list of managers")]
public void WhenIRequestAListOfManagers()
{
    WhenIRequestAListOfManagers("");
}

[When(@"I request a list of managers with the search term (.*)")]
public void WhenIRequestAListOfManagers(string searchTerm)
{
   //do stuff
}

Upvotes: 3

Marcus Hammarberg
Marcus Hammarberg

Reputation: 4822

Two things pops into my head:

Firstly I now a days don't worry to much of having loads of step definitions as long as they are short (oneliners) and calling into some sort of automation layer or DSL that helps me to automate the system under test. See this excellent presentation for inspiration.

So in that sense you could just double the step definitions with "overloads" for each case.

My first stab on a second solution was to stack attributes on top of each others for the same method. That works, but not for optional parameters. (And optional parameters doesn't work to well with reference types as DateTime, but DateTime? nullable works). If you step up your steps like that you will get an error like this:

Parameter count mismatch! The binding method 'Class1.MyGiven(Int32, Int32, Int32)' should have 1 parameters

So I fall back to my first solution like this:

    [Given(@"case one with one int '(\d+)'")]
    public void Case1(int a)
    {
        // Short but sweet step definition that calls into automation layer
    }

    [Given(@"case one with two ints '(\d+)' and '(\d+)'")]
    public void Case2(int a, int b)
    {
        // Short but sweet step definition that calls into automation layer
    }

    [Given(@"case one with three ints '(\d+)' and '(\d+)' and also '(\d+)'")]
    public void Case3(int a, int b , int c)
    {
        // Short but sweet step definition that calls into automation layer
    }

I hope I didn't cause too much confusion by going back and forth. Sorry - had no IDE ready on the bus :)

Upvotes: 7

mancaus
mancaus

Reputation: 3001

I prefer the simplicity of multiple steps, but if you want do do what you propose, you will need to craft an appropriate regex. Something like (not tested):

[Given(@"(at ([0-9-]+) (really at ([0-9-]+) |)|)(\w+) Completed a transfer form to transfer \$(\d+) to account (\d+)"]
public void TransferStep(string dummy1, DateTime? atDate, string dummy2, DateTime? reallyAtDate, string name, decimal amount, int account)

Upvotes: 5

Related Questions