2

I'm updating my cucumber version from old info.cukes to latest io.cucumber (v6.8.1) and some of my tests are failing now with java.lang.IllegalArgumentException at BuiltInParameterTransformer.java:114

How can I pass list of strings as parameter in new cucumber?

I read this answer but it doesn't work for me. You can find below an example to reproduce my problem:

  Scenario Outline: Testing lists of strings
    When Great test <first> <second> <third>
    Examples:
      | first    | second                 | third            |
      | "simple" | "listOfParams"         | "another simple" |
      | "simple" | "list,OF,params"       | "another simple" |
    @When("^Great test \"(.*?)\" \"(.*?)\" \"(.*?)\"$")
    public void great_test(String string, List<String> string2, String string3) {
        System.out.println(string);
        System.out.println(string2); // I want to get here ["listOfParams"] and ["list", "OF", "params"]
        System.out.println(string3);
    }
Marit
  • 2,174
  • 13
  • 24
makozaki
  • 2,315
  • 1
  • 5
  • 27
  • which version of cucumber are you using? – Marit Oct 15 '20 at 11:37
  • Right now `6.8.1` but it worked fine on old info.cukes. – makozaki Oct 15 '20 at 11:42
  • Are you sure there was no any other logic? There is `List string2` in your step definition. I am not sure cucumber can map such objects out of the box. – Alexey R. Oct 15 '20 at 11:45
  • 1
    Old cucumber 'info.cukes' 1.2.x was mapping such cases automatically. I read there was xstream transformer build in but it was conflicting with new features which allowed more flexibility and as I understand now for such case I need to write some custom method to split my parameters. My question here was if there is some way to keep old behavior for new library so I don't need to perform a major refactor when migrating to new library. – makozaki Oct 15 '20 at 12:43

1 Answers1

2

You can define a parameter type for your list of strings:

    @ParameterType("(?:[^,]*)(?:,\\s?[^,]*)*")
    public List<String> listOfStrings(String arg){
        return Arrays.asList(arg.split(",\\s?"));
    }

Then you can either use this parameter type in a step definition with a Cucumber Expression:

    @Given("a list of strings \"{listOfStrings}\"")
    public void a_list_of_strings_cucumber_expression(List<String> list) {
        System.out.println(list);
    }

Or you can use the exact regular expression wrapped in a capture group:

    @Given("^a list of strings \"((?:[^,]*)(?:,\\s?[^,]*)*)\"$")
    public void a_list_of_strings_regex(List<String> list) {
        System.out.println(list);
    }

Note that you can't use .* because this is reserved for the anonymous parameter type. When using the anonymous parameter type Cucumber will guess what you want to do based on the type of the argument.

And this works for Boolean, String, Numbers, ect because they have a single way to writ them down. There are however many ways to write down a list of strings so Cucumber won't guess.

    // This will complain
    @ParameterType(value = ".*", preferForRegexMatch = true)
    public List<String> listOfStrings(String arg){
        return Arrays.asList(arg.split(",\\s?"));
    }
M.P. Korstanje
  • 6,760
  • 3
  • 28
  • 43