Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Added support for string-based matchers for step definitions. #48

wants to merge 3 commits into


None yet
2 participants

Format example:

  • 'I increment the variable by %d'
  • 'I enter %s into firstname and %s into lastname'

Regexp support in step-definitions are still working as they should.

Added support for string-based matchers for step definitions.
Format example:
 - 'I increment the variable by %d'
 - 'I enter %s into firstname and %s into lastname'

jbpros commented on 8447f57 Mar 12, 2012

Thanks for the pull request, Ted.

Cucumber-ruby supplies a similar syntax:

'I increment the variable by $value'

This feature is definitely missing in Cucumber.js, as many people have reticences using regexps (to say the least!).

However, I'd rather stick with the $ syntax. Two reasons for that:

  • Keep it consistent between Cucumber implementations;
  • Do not assume things regarding what is a number/string/whatever.

[^"]* is too restrictive as a any string matcher. A more reasonable one would be [^\s]* or something similar. Using quotes to surround a string is not mandatory, we can't just force that rule.

Also, I have the feeling %d could suggest there is some typecasting going on behind the scene.

What do you think?

I'm not an expert on regular expressions, but i do agree with you about keeping the syntax the same as the ruby version of cucumber.

I think that matching for numbers/strings etc can be usefull in some situations where you build your logic for a certain datatype and when specs change, you know immediatly that your steps are being skipped because the parameter does not map to a single step.
However, on the other hand without typechecks you can see if your code works properly with other datatypes without having to add steps.

How does the ruby version of cucumber handle string-based matchers? Perhaps it is the best to keep the feature the same.


jbpros commented Mar 12, 2012

I think $-variables are simply matching any string of non-whitespace characters. Basically, it maps to ([^\s]*) or something, passing the captured string to the step definition and ignoring the actual variable name.

When one needs smarter step arguments, transforms are generally a nice way to go. It allows for both matching group reuse and typecasting.

NUMBER = Transform /^(\d+)$/ do |number|
  return number.to_i

Given /^I have #{NUMBER} cucumbers$/ do |cucumber_count|
  # cucumber_count is an integer, not a string

But of course, this is all based on regexps.

I agree, the name in the $ should not mean anything (unless someone really wants it, like in your example).

Do you want me to rewrite the code so it can use $ANYTHING and replace that with ([^\s]*) or something?


jbpros commented Mar 12, 2012

Sure, that'd be a nice addition.

Easyer string-based matchers using '$' prefixes.
 - 'I incremend the variable by $VAR1'
 - 'I enter $var into firstname and $var2 into lastname'

I have added the simpler matcher that matches on parameters with a $.

Step usage:
Given('a variable set to $nummer2', function(number, callback) {
console.log('number: ', number);

Scenario: easy maths
Given a variable set to 1
When I increment the variable by 1
Then the variable should contain 2


jbpros commented Mar 13, 2012

Great, thank you Ted.

I'm thinking it would be a good idea to introduce a "step definition pattern" that would encapsulate the string/regexp of the step definition.

Also we need some tests for this ;) Are you up to it?

While a "step definition pattern" isn't a bad idea, perhaps that would overengineer it.

What kind of tests do you have in mind?


jbpros commented Mar 14, 2012

As soon as we're dealing with a "multi-type" variable, I smell a need for encapsulation. Additionally, I try to keep constructors a simple as possible. They're then easier to test and much less responsible for business logic.

Regarding the tests, there are both features and specs. Cucumber.js is passing the cucumber-tck feature suite entirely when run from both Cucumber-ruby and Cucumber.js in addition to a few features specific to it.

But again, I can help on this if you want.

Okay. I would really appreciate the help, im not familiar with ruby and i dont know how to properly run those .tck spec tests.

I have added a testfeature that now passes in the cucumber-tck suite (running npm test).

Rewriting the code should be safe now :).
I do not know how your vision is on the encapsulation but i will let you to decide how to implement that.

Will you implement this feature in cucumber-js?


jbpros commented Mar 27, 2012

@tdekoning Don't worry, I will. I'm quite busy preparing my talks at CukeUp!, among other things.

I should be able to take care of it in ~two weeks or so. I'm sorry for this rather long delay.

Stay tuned!

@@ -34,6 +34,7 @@ Cucumber.js is still a work in progress. Here is its current status.
| [Undefined steps](https://github.com/cucumber/cucumber-tck/blob/master/undefined_steps.feature) | Done |
| [Wire protocol](https://github.com/cucumber/cucumber-tck/blob/master/wire_protocol.feature) | To do |
| [World](https://github.com/cucumber/cucumber-tck/blob/master/world.feature) | Done |
+| [String defined step definitions](https://github.com/cucumber/cucumber-tck/blob/master/stringdefined.feature) | Done |

jbpros Apr 10, 2012


There is no such feature in cucumber-tck. Do you have it on your local repo?

@@ -333,5 +353,9 @@ callback();\
this.assertExecutedNumberedScenarios(2, 3, 4);
+ Then('The string-defined scenario is finished', function(callback) {
+ callback();

jbpros Apr 10, 2012


The step definitions you added are not doing anything apart from calling back. I think you are missing something here :)

@jbpros jbpros closed this in 8aa8d9d Apr 18, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment