Specflow step argument transformation on table cel

2020-04-08 01:01发布

Has anyone solved the riddle of how to apply SpecFlow Step Argument Transformations to cells in a table, in conjunction with the SpecFlow.Assist CreateInstance/CreateSet? (code combined here to save space)

Given a table like the following:
 | Price | Zip   | Effective Date |
 | 10.00 | 90210 | in 2 days      |
When the 'given' step executes
And the table data populates a poco
Then the effective date should be transformed into a DateTime with value of 2 days from today

[Given(@"a table like the following:")]
public void GivenATableLikeTheFollowing(Table table)
{
    var temp = table.CreateInstance<Temp>();
}

internal class Temp
{
    decimal Price { get; set; }
    int Zip { get; set; }
    DateTime EffectiveDate { get; set; }
}

[Binding]
public class Transforms
{
    [StepArgumentTransformation(@"in (\d+) days?")]
    public DateTime InXDaysTransform(int days)
   {
      return DateTime.Today.AddDays(days);
   }
}

StepArgumentTransformation bindings apparently don't apply to table cell contents (since the step's argument is type Table), but somehow the SpecFlow.Assist CreateInstance/CreateSet will still transform cell data for basic types.

For example , if the Effective Date's contents are '11/13/2016' instead of 'in 2 days', the underlying poco's EffectiveDate property transforms to a DateTime just fine (or an int, decimal, etc).

I see some other solutions like applying a conversion within the step definition itself like here or creating a StepArgumentTransformation for the whole table, but... obvious cons. Update: this question is similar, but solutions also avoid mingling StepArgumentTransformation with CreateInstance/CreateSet.

There is also a section in the SpecFlow Assist Helpers docs about extending by registering value retrievers/comparers, but in my example, a DateTime set already exists. So, perhaps a custom DateTime type? It seems like perhaps there could be a check for StepArgumentTransformations on the known types, or something like that.

In the DateTime retriever, something like..

    public virtual DateTime GetValue(string value)
    {
        var returnValue = DateTime.MinValue;
        // check for StepArgumentTransformations here first?
        DateTime.TryParse(value, out returnValue);
        return returnValue;
    }

Any ideas on what I am missing to get the StepArgumentTransformation to apply to the table cell contents when using table.CreateInstance? Or is one of the mentioned solutions the best/only way?

2条回答
虎瘦雄心在
2楼-- · 2020-04-08 01:49

I have created a small prototype that can be used to reconfigure Assist to be able to pick up conversions with [StepArgumentTransformation] bindings.

My plan is to make a blog post about it, but until it is ready, maybe you can get out the essence from this gist. (I did it a year ago for SpecFlow v2.0, so some smaller adaptions might be necessary.)

https://gist.github.com/gasparnagy/a478e5b7ccb8f557a6dc

查看更多
爷、活的狠高调
3楼-- · 2020-04-08 01:49

I don't think what you want is implemented currently, but theoretically I think it could be implemented. You can probably implement a new, enhanced DateTimeValueRetriever yourself which checks to see if the string is parseable as a datetime first and if not checks if any of the [StepArgumentTransformation] methods can parse it, and then replace the current DateTimeValueRetriever with your enhanced one. Then you could submit a pr offering your new version as an enhancement to the existing version, and see what the appetite is.

查看更多
登录 后发表回答