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
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
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
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With