Optional Arguments in Step Definitions

4,212 views
Skip to first unread message

Jeff Nyman

unread,
Jan 16, 2012, 6:23:58 PM1/16/12
to Cukes
I have statements like these in my specifications:

====================================
Given the default "cleartrial administrator" user

Given the default "clinical administrator" user is logged in

Given the default "clinical administrator" user with
| Setting | Value |
| Role | Power User |
| Edit Mode | Expert |
| Additional | Wbs Editor |
| Additional | Exchange Rates Administrator |
| Additional | Can Access WS-API |
====================================

I can match these with the following expression:

Given (/(?:the |a |an |)?(any |default |random )?"([^"]*)"
user(?:.*)/) do |descriptor, role, settings=nil|

The problem is that I can't seem to have the third parameter,
settings, default to nil if it's not provided. If I have it set to
nil, as I do above, then the first two Given statements match without
problem. However, the third one will produce this error:

Your block takes 2 arguments, but the Regexp matched 3 arguments.

If I don't allow the third parameter to take a default value, then the
third Given works but now the other two return an error like this:

Your block takes 3 arguments, but the Regexp matched 2 arguments.

I know I could just make matchers for different statement patterns but
ideally I'd like to use what I have above because it really
streamlines the process. Plus, given that Ruby obviously allows
parameters that take default values if they are not provided, I'm not
sure why this isn't working.

Can anyone spot something that I'm doing wrong?

- Jeff

Jeff Nyman

unread,
Jan 16, 2012, 6:38:14 PM1/16/12
to Cukes
Arrgh. Never mind. I figured it out on my own; a mistake on my part.
For those who may have a similar question, I was making a mistake in
how I specified the parameter. I originally did this:

Given (/(?:the |a |an |)?(any |default |random )?"([^"]*)"
user(?:.*)/) do |descriptor, role, settings=nil|

What I should have done is this:

Given (/(?:the |a |an |)?(any |default |random )?"([^"]*)"
user(?:.*)/) do |descriptor, role, *settings|

The change is not providing a default value but rather specifying that
the parameter itself is entirely optional. So far that seems to do the
trick.

- Jeff

Jeff Nyman

unread,
Jan 18, 2012, 2:01:10 PM1/18/12
to Cukes
Actually, just for accuracy in case anyone ever reads this thread, as
it turns out my solution doesn't work at all, at least if you use
tables. Cucumber drops tables if you use an optional parameter.

For example, say you have this:

===============================
Scenario: Test it out
Given I do something to with
| Setting | Value |
| Some Setting | Some Value |
===============================

and you have a matcher like this

===============================
Given (/I do something to with$/) do |table|
puts ("Table: #{table}")
puts ("Table class: #{table.class}")
end
===============================

You will get this output:

===============================
Given I do something to with
Specifics:
| Setting | Value |
| Some Setting | Some Value |
Specifics class: Cucumber::Ast::Table

1 scenario (1 passed)
1 step (1 passed)
0m4.635s
===============================

Now change the clause line of the matcher like this:

===============================
Given (/I do something to with$/) do |*table|
===============================

All I did here is make the parameter optional.

===============================
Given I do something to with
Specifics: [
| Setting | Value |
| Some Setting | Some Value |
]
Specifics class: Array
1 scenario (1 passed)
1 step (1 passed)
0m4.635s
===============================

As you can see, now the table is an array.

As I mentioned before, I can't do something like this:

Given (/I do something(?: to)? with$/) do |specifics=[]|

Here I've provided a default value for the parameter if one is not
passed but that doesn't work as you get this error:

Your block takes 0 arguments, but the Regexp matched 1 argument.

As far as the rationale, I was trying to have a single step that would
match a phrase that either did or did not have a table:

Given a default user

and

Given a default user with
| table goes here |

It's looking like I'm going to have to separate those steps out. The
problem is that each step (which uses page objects) will then have
lots of duplicated code.

- Jeff

Matt Wynne

unread,
Jan 20, 2012, 7:40:07 PM1/20/12
to cu...@googlegroups.com

On 18 Jan 2012, at 19:01, Jeff Nyman wrote:

> It's looking like I'm going to have to separate those steps out. The
> problem is that each step (which uses page objects) will then have
> lots of duplicated code.

Just factor the duplicated code out into a helper method. It's much easier to read two simple step defs than a gnarly regexp.

cheers,
Matt

--
Freelance programmer & coach
Author, http://pragprog.com/book/hwcuc/the-cucumber-book (with Aslak Hellesøy)
Founder, http://relishapp.com
+44(0)7974430184 | http://twitter.com/mattwynne

Reply all
Reply to author
Forward
0 new messages