Search code examples
javacucumbercucumber-jvmcucumber-javacucumber-junit

Parse integer list from Scenario outline's example table in cucumber java


I have to write a BDD test using cucumber with java and I would like to parse an integer list from every line of my example table and pass this list to my step method using the latest version of cucumber (4.2.6). So I got the following step definition in my feature file:

Scenario Outline: Some scenarion
    Given a list of integer: <integer_list> 

    Examples:
      | integer_list   |
      | 2, 3, 5, 6     | 
      | 3, 12, 45, 5, 6| 

And I would need something like this in my code:

   @Given("a list of integer: (\\d+.)")
    public void storeIntegerList(List<Integer> integers) {
     System.out.println(integers.size());
    }

Unfortunately, I can't find a way to handle parse these values into a list. It's either doesn't find the step method (I've tried lots of different regexp) or throws an exception where inform me that my numbers can't be transformed to a list.

As a workaround I parse the list as string then split it. However, I can't imagine that in 2019 there is no better way to do this.

The workaround:

Scenario Outline: Some scenarion
    Given a list of integer: "<integer_list>" 

    Examples:
      | integer_list   |
      | 2, 3, 5, 6     | 
      | 3, 12, 45, 5, 6| 


@Given("a list of integer: {string}")
    public void storeIntegerList(String integers) {
        List<String> integersAsString = Arrays.asList(integers.split(","));
        List<Integer> integerList = integersAsString.stream().map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList());
        System.out.println(integerList.size());        
    }


Solution

  • I did as @Grasshopper advised and implemented my own TypeRegistryConfigurer and put it next to my runner class (to be on the Glue path):

    import cucumber.api.TypeRegistry;
    import cucumber.api.TypeRegistryConfigurer;
    import io.cucumber.cucumberexpressions.ParameterType;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Locale;
    import java.util.stream.Collectors;
    
    import static java.util.Locale.ENGLISH;
    
    public class TypeRegistryConfiguration implements TypeRegistryConfigurer {
        @Override
        public Locale locale() {
            return ENGLISH;
        }
    
        @Override
        public void configureTypeRegistry(TypeRegistry typeRegistry) {
            typeRegistry.defineParameterType(new ParameterType<>(
                    "integerList",  //this name can be used in the step method
                    "(-?[0-9]+(,\\s*-?[0-9]+)*)", //regexp to match to a comma separated integer list which can contain negative numbers and whitespaces as well
                    List.class,  //the expected parameter type
                    this::transform  // equivalent to (String s) -> this.transformer(s), this is the transformer method which will be used to create the desired step parameter 
            ));
        }
    
    //transforms the string form to an integer list
        private List<Integer> transform(String integers) {
            List<String> integersAsString = Arrays.asList(integers.split(","));
            return integersAsString.stream().map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList());
        }
    }
    
    

    After that I'm able to do the following in my step class:

       @Given("a list of integer: {integerList}")
        public void storeIntegerList(List<Integer> integers) {
         System.out.println(integers.size());
        }
    

    And the feature file can be used like this:

    Scenario Outline: Some scenarion
        Given a list of integer: <integer_list> 
    
        Examples:
          | integer_list     |
          | 2, 3, 5, 6       | 
          | 3, -12, 45, -5, 6|