Search code examples
c#regexbddspecflowacceptance-testing

list of numbers as parameter in specflow test step


I am looking for a way to have a step definition such as:

Given a collection of numbers 1,2,3,4

and map that to a step definition with either a int[], List, or IEnumerable

the regex (\d+(,\d+)*) matches, but means I need two parameters.

At present I have

[Given(@"a collection of numbers (\d+(,\d+)*)")]
public void givencollectionofnumbers(string p0, string p1)
{
    //p0 is "1,2,3,4"
    //p1 is ",4"
}

I have a simple workarouns that is

[Given(@"a collection of numbers (.*)")]
public void givencollectionofnumbers(string p0)
{
    var numbers = p0.Split(',').Select(x => int.Parse(x));
}

but I would like to do this in a more elegant manner potentially changing the type of the numbers to doubles and also ensuring that the regex only maches lists of numbers.

I also would rather not use a table for this as it seems excessive for simple list of data

Can anyone help with this


Solution

  • I just resolve the same issue on my project: this will do the trick

    ((?:.,\d+)*(?:.\d+))
    

    If you want to accept single int as well, use this instead:

    ((?:.,\d+)*(?:.+))
    

    There are 2 problems with your proposition :

    • Specflow try to match it as 2 parameters, when you need only 1. But I was unable to find a clear explanation of why it did that in the documentation

    • you definitely need a StepArgumentTransformation to transform your input string in any enumerable

    So your final step functions will look like that:

    [Given(@"foo ((?:.,\d+)*(?:.+))")]
    public void Foo(IEnumerable<int> ints)
    {
    }
    
    [StepArgumentTransformation(@"((?:.,\d+)*(?:.+))")]
    public static IEnumerable<int> ListIntTransform(string ints)
    {
        return ints.Split(new[] { ',' }).Select(int.Parse);
    }
    

    And you receive an Enumerable int in your Foo function.

    Hope it helps.