Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default Values Specflow Step Definitions

I'm starting out in the world of SpecFlow and I have come across my first problem. In terms of keeping my code DRY I'd like to do the following:

Have two scenarios:

Given I am on a product page
And myfield equals todays date
Then...

Given I am on a product page
And myfield equals todays date plus 4 days
Then...

I was hoping to use the following Step Definition to cover both variants of my And clause:

[Given(@"myfield equals todays date(?: (plus|minus) (\d+) days)?")]
public void MyfieldEqualsTodaysDate(string direction, int? days)
{
//do stuff
}

However I keep getting exceptions when SpecFlow tries to parse the int? param. I've checked the regular expression and it definitely parses the scenario as expected. I'm aware that I could so something as crude as method overloading etc, I was just wondering if SpecFlow supported the idea of default parameter values, or indeed another way to achieve the same effect.

Many Thanks

like image 704
Gavin Osborn Avatar asked Feb 07 '11 14:02

Gavin Osborn


3 Answers

The default values are not supported (yet), but for your concrete case, I can suggest the following:

SpecFlow supports creating "step argument transformations". With them, you can create methods that can parse datetime from different patterns:

[StepArgumentTransformation("todays date")]
public DateTime TransformToday()
{
  return DateTime.Today;
}
[StepArgumentTransformation("todays date (plus|minus) (\d+) days")]
public DateTime TransformOtherDay(string direction, int days)
{
  //...
}

After that, you just need to use a DateTime param in your steps and the rest is done by SpecFlow...

[Given(@"myfield equals (.*)")]
public void MyfieldEqualsTodaysDate(DateTime date)
{
  //do stuff
}

you can see more examples at https://github.com/techtalk/SpecFlow/wiki/Step-Argument-Conversions

like image 157
Gaspar Nagy Avatar answered Oct 18 '22 14:10

Gaspar Nagy


A friend of mine uses the following technique

Given I am on a product page And myfield equals {TODAY}

Given I am on a product page And myfield equals {TODAY+4}

You can then parse the special phrase in the step defs

[Given(@"myfield equals ("SOME MATCHING REGEX")]
public void MyfieldEqualsTodaysDate(string date) {
//parse TODAY or you could use TOMORROW you get the idea
}

like image 2
Johnno Nolan Avatar answered Oct 18 '22 13:10

Johnno Nolan


Your steps seem phrased in fairly developer centric language.

What happens if you phrase them in stakeholder language instead?

Given I am on the product page
And my product is due for delivery today

Given I am on the product page
And my product is due for delivery in 4 days

Given I am on the product page
And my product was due for delivery 3 days ago

Now you can use the regexp to match those different steps, and remove the duplication at a lower level.

[Given(@"my product is due for delivery today")]
public void GivenTheProductIsDueToday() {
    var dueDate = Date.Today;
    DoOtherStuffWith(dueDate);
}

[Given(@"my product is due for delivery in (.*) days")]
public void GivenTheProductIsDueIn(int days) {
    var dueDate = Date.Today.AddDays(days);
    DoOtherStuffWith(dueDate);
}

[Given(@"my product was due for delivery (.*) days ago")]
public void GivenTheProductWasDue(int days) {
    var dueDate = Date.Today.AddDays(-1*days);
    DoOtherStuffWith(dueDate);
}

I don't use SpecFlow yet but I hope this makes sense. BDD's focus is more about enabling the conversation between business and stakeholders than it is about testing or automation. Compromising that for DRY may not be helpful in the long run.

like image 2
Lunivore Avatar answered Oct 18 '22 14:10

Lunivore