Capturing Arguments

You’ll notice that in the step we’ve been using as an example, we’ve talked about the sum of $100 the whole time. What if we had another scenario where we needed to deposit a different amount of money into the account? Would we need another step definition, like this?

 
Given /I have deposited $100 in my Account/ ​do
 
# TODO: code goes here
 
end
 
 
Given /I have deposited $250 in my Account/ ​do
 
# TODO: code goes here
 
end

Happily, we don’t. This is where the flexibility of regular expressions comes into play. We can use two of regular expressions’ most useful features here to capture any dollar amount as an argument to the step definition. Those features are capture groups and wildcards.

Capture Groups

When you surround part of a regular expression with parentheses, it becomes a capture group. Capture groups are used to highlight particular parts of a pattern that you want to lift out of the matching text and use. In a Cucumber step definition, the text matched within each capture group is passed to the code block as an argument:

 
Given /I have deposited $(100) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

Here the block argument amount will receive the string value 100 when this step definition matches. The previous example is a bit silly, because this regular expression is still only ever going to match steps that talk about the amount of $100. We need to use a wildcard inside the capture group to open it up to other values.

Alternation

There are a few different ways to specify a wildcard in a regular expression. One of the simplest is alternation, where we express different options separated by a pipe character |, like this:

 
Given /I have deposited $(100|250) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

This step definition will now match a step with either of the two values 100 or 250 in it, and the number will be captured and passed to the block as an argument. Alternation can be useful if there are a fixed set of values that you want to accept in your step definition, but normally you’ll want something a little looser.

The Dot

The dot is a metacharacter, meaning it has magical powers in a regular expression. Literally, a dot means match any single character. So, we can try this instead:

 
Given /I have deposited $(...) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

That will now match a step with any three-figure dollar sum and send the matched amount into the block. This is definitely a step in the right direction, but there are a couple of problems with what we’ve done. For one, remember that the dot matches any character, so we could end up capturing letters in here instead of numbers. More importantly, what if we wanted a step that deposits just $10 in the account, or $1,000? This step definition won’t match those steps because it’s always looking for three characters. We can fix this by using a modifier.

Joe asks:
Joe asks:
What If I Actually Want to Match a Dot?

Any of the metacharacters like the dot can be escaped by preceding them with a backslash. So, if you wanted to specifically match, say 3.14, you could use /3.14/.

You might have noticed that there’s a backslash in front of the dollar amount in the step definition we’re using. That’s because $ itself is a metacharacter (it’s an anchor, which we’ll explain later), so we need to escape to make it match a normal dollar sign.

The Star Modifier

In regular expressions, a repetition modifier takes a character (or metacharacter) and tells us how many times over it can appear. The most flexible modifier is the star:

 
Given /I have deposited $(.*) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

The star modifier means any number of times. So, with .* we’re capturing any character, any number of times. Now we’re getting somewhere. This will definitely allow us to capture all those different amounts. But there’s still a problem.

The star modifier is a bit of a blunt instrument. Because we’re using it with the dot that matches any character, it will gobble up any text at all up until the phrase in my Account. This is why, in regex terminology, the star modifier is known as a greedy operator. For example, it would happily match this step:

 
Given ​I have deposited $1 and a cucumber in my Account

Ridiculously, the amount argument captured by our regular expression in this case would be 1 and a cucumber. We need to be a bit more specific about the characters we want to match so that we just capture numbers. Instead of a dot, we can use something else.

Character Classes

Character classes allow you to tell the regular expression engine to match one of a range of characters. You just place all of the characters you would accept inside square brackets:

 
Given /I have deposited $([0123456789]*) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

For a continuous range of characters like we have, you can use a hyphen:

 
Given /I have deposited $([0-9]*) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

Now we’ve restricted the character we’ll accept to be numeric. We’re still modifying the character with the star to accept any number of them, but we’re now being specific that we’ll accept only a continuous string of numbers.

Shorthand Character Classes

For common patterns of characters like [0-9], there are a few shorthand character classes that you can use instead. You may find this just makes your regular expressions more cryptic, but there are only a few to learn. For a digit, you can use d as a shorthand for [0-9]:

 
Given /I have deposited $(d*) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

See Useful Shorthand Character Classes for more examples.

There’s just one last problem with this. Can you see what it is?

The Plus Modifier

The star is one example of a repetition modifier, but there are others. A subtle problem with the star is that any number of times can mean zero.

So, this step would match:

 
Given ​I have deposited $ in my Account

That’s no good. To fix this, we can use the + modifier, which means at least once:

 
Given /I have deposited $(d+) in my Account/ ​do​ |amount|
 
# TODO: code goes here
 
end

There we go. We took a rambling route to get to the answer, but on the way we’ve visited almost every one of the features of regular expressions that are useful to us when building Cucumber step definition. There are only a couple more to cover.

Try This

Imagine you’re building a system for airport departure lounge screens. You need to be able to capture examples of flight codes from the Cucumber scenarios. Can you write a single step definition that can capture the flight codes from all of these steps?

 
Given the flight EZY4567 is leaving today
 
...
 
Given the flight C038 is leaving today
 
...
 
Given a flight BA01618 is leaving today

Start by writing a step definition that works for the first step, and then make it more and more generic so that it works with the other steps too.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.56.12