Converting data to a Table in SpecFlow

The use case for this is, I have a step Set fields on view which takes a table like this

Scenario: With table
  Given Set fields on view 
    | A  | B  | C  |
    | a1 | b1 | c1 |
    | a2 | b2 | c2 |      
    | a3 | b3 | c3 |                            

The code for this step, currently just outputs the data set to it to the console or log file, so looks like this

[Given(@"Set fields on view")]
public void GivenFieldsOnView(Table table)
{
   table.Log();
}

Now in some cases, I want to set fields on a view using an Examples. So in the current case we’re sending multiple rows in one go, but maybe in some situations we want to set fields, one row at a time, so we uses Examples like this

Scenario Outline: Convert To Table
  Given Set fields on view A=<A>, B=<B>, C=<C>

  Examples:
    | A  | B  | C  |
    | a1 | b1 | c1 |
    | a2 | b2 | c2 |      
    | a3 | b3 | c3 |            

We’ll then need a new step that looks like this

[Given(@"Set fields on view (.*)")]
public void GivenFieldsOnView(string s)
{
}

Ofcourse we can now split the variable s by comma, then split by = to get our key values, just like a Table and there’s nothing wrong with this approach, but an alternative is to have this transformation as a StepArgumentTransformation. So our code above would change to

[Given(@"Set fields on view (.*)")]
public void GivenFieldsOnView2(Table table)
{
   table.Log();
}

and now in our hook class we’d have something like this

[Binding]
public class StepTransformer
{
  [StepArgumentTransformation]
  public Table TransformToTable(string input)
  {
    var inputs = input.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
    var d = inputs.Select(s =>
      s.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
        .ToDictionary(v => v[0], v => v[1]);

    // this only handles a single row 
    var table = new Table(d.Keys.ToArray());
    table.AddRow(d.Values.ToArray());
    return table;
  }
}

Note: This is just an example, with no error handling and will only convert a string to a single row, it’s just a demo at this point.

So, now what we’ve done is create a transformer which understands a string syntax such as K1=V1, K2=V2… and can convert to a table for us.

I know that you’re probably asking, why, we could we not just execute the same code in the public void GivenFieldsOnView(string s) method ourselves. Well you could ofcourse do that, but now you’ve got a generic sort of method for making such transformations for you.

What I really wanted to try to do is use a single step to handle this by changing the regular expression, i.e. we have one method for both situations. Sadly I’ve not yet found a way to achieve this, but at least we can reduce the code to just handle the data as tables.