How to transform Spec-flow table data into differe

2019-02-23 17:45发布

I need to transform Spec-flow table data that we get via table.CreateInstance() or table.CreateSet() . I am using Spec flow for DB testing and in some cases, Table field values needs to be mapped to different values as DB tables are storing codes instead of the the values we have entered in tables of feature files. I do not want to include the codes in feature files as it reduces the readability. For example, If I have entered Single for status as mentioned below, I want it to be mapped or transform to S in the data transfer object / POCO. What is the best approach ? Thanks in advance.

Given I entered the following data into the new account form:
| Name        | Birthdate | Status      |
| John Butcher| 2/2/1902  | Single      |

4条回答
Root(大扎)
2楼-- · 2019-02-23 18:10

I posed a similar question with a different example here. Seems like it should be possible to apply StepArgumentTransforms to CreateInstance/CreateSet, but just hasn't been implemented yet for basic types that already get transformed in the table conversion.

In your case (unlike mine), I think you could do it relatively easily with a custom ValueRetriever.

查看更多
家丑人穷心不美
3楼-- · 2019-02-23 18:13

As Sam pointed out, we can use StepArgumentTransformarion or an approach similar to below. Add if else inside the extension methods if you want to map Value1 to Code1 for one type and Value1 to CodeX in another type using typeof(T).Name.Equals(typeof(yourtype).Name) as the condition

 public static IEnumerable<T> CreateSetWithValueTransfer<T>(this Table table)
    {
        var mapper = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
        {
            {"Value1", "Code1"},
            {"value2", "Code2"}
        };

        var set = ChangeValues(table, mapper);
        return set.CreateSet<T>();
    }


    private static Table ChangeValues(Table table, Dictionary<string, string> mapper)
    {
        var mappedTable = new Table(table.Header.ToArray());
        foreach (var row in table.Rows)
        {
            mappedTable.AddRow(row.Values.Select(x => mapper.ContainsKey(x) ? mapper[x] : x).ToArray());
        }
        return mappedTable;
    }
查看更多
祖国的老花朵
4楼-- · 2019-02-23 18:18

I've started using "Test Models," which ended up being view models for my spec flow tests.

Using your example:

Given I entered the following data into the new account form:
    | Name        | Birthdate | Status      |
    | John Butcher| 2/2/1902  | Single      |

The Domain Model:

public class Account
{
    public string Name { get; set; }
    public DateTime? Birthdate { get; set; }
    public string Status { get; set; }
}

And the "Test Model":

public class AccountForm
{
    public string Name { get; set; }
    public DateTime? Birthdate { get; set; }
    public string Status { get; set; }

    public Account CreateInstance()
    {
        return new Account()
        {
            Name = Name,
            Birthdate = Birthdate,
            Status = Status.Substring(0, 1)
        };
    }
}

The step defintion:

[Given(@"Given I entered the following data into the new account form:")]
public void GivenIEnteredTheFollowingDataIntoTheNewAccountForm(Table table)
{
    var form = table.CreateInstance<AccountForm>();
    var account = form.CreateInstance();

    // save to the database
}

For this one particular example it might be more than you need, but I've found this pattern works well when the data in the Scenario needs to be in a human readable format, which gets translated to a complex format in your Domain Model.

查看更多
【Aperson】
5楼-- · 2019-02-23 18:19

I'm not aware of anyway to do this automatically, so I can only think of two possibilities.

  1. Don't use the CreateInstance or CreateSet methods and instead do all of the mapping manually, but encapsulate it in a [StepArgumentTransformation]
  2. Use the methods you are using but then afterwards overwrite the automatically generated 'Single' values with 'S' after the instances have been created.
查看更多
登录 后发表回答