Optional parameters with Specflow

Carlo V. Dango picture Carlo V. Dango · Apr 23, 2012 · Viewed 10.3k times · Source

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 

Answer

Marcus Hammarberg picture Marcus Hammarberg · Apr 24, 2012

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 :)