Gherkin-like multi-line table arguments

2,568 views
Skip to first unread message

Steve Fox

unread,
Apr 29, 2011, 4:10:32 PM4/29/11
to robotframe...@googlegroups.com
I am in the process of converting my team's tests from Cucumber/Watir to RobotFramework/Selenium. The BDD style tests support in RF is working wonderfully with one exception. RF does not easily support the multi-line table arguments that Cucumber/Gherkin does (see https://github.com/aslakhellesoy/cucumber-rails-test/blob/master/features/manage_lorries.feature). I've managed a work-around by using the ellipsis feature, but it's less than elegant.

For example, the Gherkin statement:

Given the following lorries:
  | name   | colour |
  | name 1 | green  |
  | name 2 | yellow |


can be written in RF as

Given the following lorries:
  ...  | name   | colour |
  ...  | name 1 | green  |
  ...  | name 2 | yellow |


but my Python function receives a list of strings rather than a two-dimensional list. I then have to split and strip the strings in order to get just the values.

In order for my ideal situation to work, I think RF would have to support two-dimensional lists. Is this even feasible? Does anyone have a better solution? Thanks.

Bryan Oakley

unread,
Apr 29, 2011, 5:05:30 PM4/29/11
to robotframe...@googlegroups.com
On Fri, Apr 29, 2011 at 3:10 PM, Steve Fox <li...@thefoxhome.net> wrote:
> I am in the process of converting my team's tests from Cucumber/Watir to
> RobotFramework/Selenium. The BDD style tests support in RF is working
> wonderfully with one exception. RF does not easily support the multi-line
> table arguments that Cucumber/Gherkin does (see
> https://github.com/aslakhellesoy/cucumber-rails-test/blob/master/features/manage_lorries.feature).
> I've managed a work-around by using the ellipsis feature, but it's less than
> elegant.
> ...

> but my Python function receives a list of strings rather than a
> two-dimensional list. I then have to split and strip the strings in order to
> get just the values.
>
> In order for my ideal situation to work, I think RF would have to support
> two-dimensional lists. Is this even feasible? Does anyone have a better
> solution? Thanks.

With a little bit of cleverness it's possible now. For example, your
keyword "Given the following lorries" could do nothing but create an
empty suite variable. Then, create a keyword named ":" that creates a
list from its arguments and appends that to the suite variable. Call
that keyword several times and you end up with a list of lists,
effectively a two-dimensional array. Any other keywords that follow
then just need to use the suite variable created by those two
keywords.

Your test would look something like this:

Given the following lorries:
: | name | colour |
: | name 1 | green |
: | name 2 | yellow |

Do something with the variable

I have some tests that test functions that process robot tests (robot
testing robot!) and I use this technique to embed a test case inside a
test case. I end up with a list of lists, with each element in the
list itself a list representing one row from a test case. In effect, a
2D array.

BTW, there's nothing special about ":" other that it is unobtrusive.
You could just as easily call it "_" or "table row" or something.

--
Bryan Oakley
Orbitz Worldwide

Pekka Klärck

unread,
May 2, 2011, 6:20:26 PM5/2/11
to li...@thefoxhome.net, robotframe...@googlegroups.com
2011/4/29 Steve Fox <li...@thefoxhome.net>:

> I am in the process of converting my team's tests from Cucumber/Watir to
> RobotFramework/Selenium. The BDD style tests support in RF is working
> wonderfully with one exception.

Welcome aboard and great to hear that you like Robot's BDD features.
Hopefully we can figure out a way to make it even better!

> RF does not easily support the multi-line
> table arguments that Cucumber/Gherkin does (see
> https://github.com/aslakhellesoy/cucumber-rails-test/blob/master/features/manage_lorries.feature).
> I've managed a work-around by using the ellipsis feature, but it's less than
> elegant.
>
> For example, the Gherkin statement:
>
> Given the following lorries:
>   | name   | colour |
>   | name 1 | green  |
>   | name 2 | yellow |

I didn't know Cucumber had this kind of a feature but it looks pretty
handy. According to the docs [1] the step definition doesn't actually
get a list of list but a custom Cucumber::Ast::Table object that has
several convenience methods for accessing the data.

[1] https://github.com/aslakhellesoy/cucumber/wiki/multiline-step-arguments

> can be written in RF as
>
> Given the following lorries:
>   ...  | name   | colour |
>   ...  | name 1 | green  |
>   ...  | name 2 | yellow |
>
> but my Python function receives a list of strings rather than a
> two-dimensional list. I then have to split and strip the strings in order to
> get just the values.

An easy to to avoid the need of splitting and stripping is formatting
the data either like this:

Given the following lorries:
| ... | name | colour |
| ... | name 1 | green |
| ... | name 2 | yellow |

or

Given the following lorries:
... name colour
... name 1 green
... name 2 yellow

Notice that the first example uses the pipe-and-space-separated plain
text format in combination with the more common space-separated format
[2]. In both cases the `Given the following lorries:` keyword gets
altogether six arguments and you just needed to construct a list of
list yourself. In Python (if you omit the colon) you can use, for
example, this code:

def given_the_following_lorries(*lorries):
lorries_as_list_of_tuples = zip(lorries[:-1:2], lorries[1::2])
# your code continues here ...

We could also add a new keyword into Collections library [3] for
converting a list into a list of list.

[3] http://code.google.com/p/robotframework/wiki/CollectionsLibrary

> In order for my ideal situation to work, I think RF would have to support
> two-dimensional lists. Is this even feasible? Does anyone have a better
> solution? Thanks.

Bryan already explained a very cool hack that adds custom syntax for
this purpose with a special `:` keyword. If there is a larger need for
list of lists as arguments, adding build-in syntax for them is
possible too. We first needed to agree on the syntax and how the
argument is passed to the keyword.

Cheers,
.peke
--
Agile Tester/Developer/Consultant :: http://eliga.fi
Lead Developer of Robot Framework :: http://robotframework.org

Steve Fox

unread,
May 3, 2011, 6:24:36 PM5/3/11
to Pekka Klärck, robotframe...@googlegroups.com
On Mon, May 2, 2011 at 5:20 PM, Pekka Klärck <pe...@iki.fi> wrote:
>
> I didn't know Cucumber had this kind of a feature but it looks pretty
> handy. According to the docs [1] the step definition doesn't actually
> get a list of list but a custom Cucumber::Ast::Table object that has
> several convenience methods for accessing the data.
>
> [1] https://github.com/aslakhellesoy/cucumber/wiki/multiline-step-arguments

Very nice. I hadn't come across that page so I didn't realize how it
was implemented.

> Given the following lorries:
>  ...   name    colour
>  ...   name 1  green
>  ...   name 2  yellow

I had tried this, but didn't like how I got everything in a single list.

> In both cases the `Given the following lorries:` keyword gets
> altogether six arguments and you just needed to construct a list of
> list yourself. In Python (if you omit the colon) you can use, for
> example, this code:
>
> def given_the_following_lorries(*lorries):
>    lorries_as_list_of_tuples = zip(lorries[:-1:2], lorries[1::2])
>    # your code continues here ...

An interesting approach I hadn't considered. Unfortunately it's still
a bit more munging than would be nice.

> We could also add a new keyword into Collections library [3] for
> converting a list into a list of list.
>
> [3] http://code.google.com/p/robotframework/wiki/CollectionsLibrary

A keyword that would accept an argument for the position to split the
list at? That sounds like a fairly easy way to get something a little
cleaner.

> Bryan already explained a very cool hack that adds custom syntax for
> this purpose with a special `:` keyword. If there is a larger need for
> list of lists as arguments, adding build-in syntax for them is
> possible too. We first needed to agree on the syntax and how the
> argument is passed to the keyword.

For some reason, Google Groups didn't email me of Bryan's post so I
didn't see it until your response. I'll give that a try. I think
supporting "table" arguments would be a great default feature for
Robot. I like the idea of using the colon keyword as it complements
the ellipses keyword, being they are both argument modifiers.

Thank you Bryan and Pekka for your advice!

--
Steve Fox

Thomas Jaspers

unread,
May 13, 2011, 4:51:52 AM5/13/11
to robotframework-users
Hi,

we wanted to do something similar and have described our approach
here:
http://blog.codecentric.de/en/2009/11/givenwhenthen-and-example-tables-using-the-robot-framework/

Maybe it gives some additional ideas :).

Cheers
- Thomas

On 4 Mai, 00:24, Steve Fox <li...@thefoxhome.net> wrote:

Pekka Klärck

unread,
May 16, 2011, 6:33:36 PM5/16/11
to Steve Fox, robotframe...@googlegroups.com
Hi Steve,

and sorry for not getting back to this earlier.

2011/5/4 Steve Fox <li...@thefoxhome.net>:


> On Mon, May 2, 2011 at 5:20 PM, Pekka Klärck <pe...@iki.fi> wrote:
>>
>> We could also add a new keyword into Collections library [3] for
>> converting a list into a list of list.
>>
>> [3] http://code.google.com/p/robotframework/wiki/CollectionsLibrary
>
> A keyword that would accept an argument for the position to split the
> list at? That sounds like a fairly easy way to get something a little
> cleaner.

This keyword would probably be pretty trivial to implement. Or
actually keywords as there probably should be a keyword also for
flattening such a list of list. Please submit an enhancement request
to the issue tracker if you think it is useful.

>> Bryan already explained a very cool hack that adds custom syntax for
>> this purpose with a special `:` keyword. If there is a larger need for
>> list of lists as arguments, adding build-in syntax for them is
>> possible too. We first needed to agree on the syntax and how the
>> argument is passed to the keyword.
>
> For some reason, Google Groups didn't email me of Bryan's post so I
> didn't see it until your response. I'll give that a try. I think
> supporting "table" arguments would be a great default feature for
> Robot. I like the idea of using the colon keyword as it complements
> the ellipses keyword, being they are both argument modifiers.

Did you try it? How well did it work?

Steve Fox

unread,
May 17, 2011, 9:20:52 AM5/17/11
to Thomas Jaspers, robotframework-users
On Fri, May 13, 2011 at 3:51 AM, Thomas Jaspers <trit...@googlemail.com> wrote:
> we wanted to do something similar and have described our approach
> here:
> http://blog.codecentric.de/en/2009/11/givenwhenthen-and-example-tables-using-the-robot-framework/

Thomas,

I had found your post when I was first looking for a solution to this,
and it was great to see an example of how to combine the BDD and
Data-Driven formats. Unfortunately it's not quite what I'm trying to
achieve, which is tabular arguments. Rather than a table of multiple
arguments, I would like one argument to hold a single two-dimensional
list of data. Thank you for your help!

--
Steve Fox

Steve Fox

unread,
May 20, 2011, 2:11:41 PM5/20/11
to Pekka Klärck, robotframe...@googlegroups.com
On Mon, May 16, 2011 at 5:33 PM, Pekka Klärck <pe...@iki.fi> wrote:
> 2011/5/4 Steve Fox <li...@thefoxhome.net>:

>> For some reason, Google Groups didn't email me of Bryan's post so I
>> didn't see it until your response. I'll give that a try. I think
>> supporting "table" arguments would be a great default feature for
>> Robot. I like the idea of using the colon keyword as it complements
>> the ellipses keyword, being they are both argument modifiers.
>
> Did you try it? How well did it work?

Unfortunately I'm under a deadline right now and haven't had any time
to devote to this. I will be getting to it as soon as I have a moment
to spare. Sorry for not being responsive.

--
Steve Fox

Pekka Klärck

unread,
May 24, 2011, 6:04:40 PM5/24/11
to Steve Fox, robotframe...@googlegroups.com
2011/5/20 Steve Fox <li...@thefoxhome.net>:

No worries. If we end up adding new syntax to the framework the
decision should not be made in hurry.

Steve Fox

unread,
Jun 23, 2011, 5:07:08 PM6/23/11
to robotframe...@googlegroups.com, Steve Fox
I finally had a bit of time to play with Bryan's suggestion to create the ':' operator. This definitely worked but having to use the additional verification step after the table made the tests read a little funny.

In the meanwhile, my team has hit several limitations trying to use RF as a Cucumber replacement. We have since switched to Lettuce <www.lettuce.it> because supports most of the Cucumber features.

Thank you Pekka and Bryan for your help. RF works great for certain use cases,
but unfortunately not mine.

In case you're curious, these are the issues we had with RF:

No support for regular expressions in keywords. This causes the number of
keywords to grow. Keyword variables help with this, but I could not get them
to work with multi-line ("table") arguments.

We really want to work in plain-text files. The 2-or-more-spaces format is
hard to read though and the pipe-separated format requires pipes to begin the
line, which looks funny in a BDD/Gherkin format.

Cannot access the pdb prompt when a breakpoint is set, due to stdio/stdin
being redirected. This made our tests considerably more difficult to
debug.

Exceptions in tests kill Robot. This prevents cleanup from occuring. We use
lots of assertions which trigger this.
Reply all
Reply to author
Forward
0 new messages