Reputation: 8394
I have a Cucumber step that looks like this:
When I enter the credentials for the user
and another that says
When I enter the correct credentials for the user
Corresponding step definitions are:
@When("I enter the ([^\"]*) for the user$")
public void stepDefinition(String cred){
//code
}
@When("I enter the correct ([^\"]*) for the user$")
public void otherStepDefinition(String cred){
//other code
}
But my second cucumber step ("I enter the correct credentials for the user") is matched by the first step definition, only with the word "correct" added to the credentials.
Upvotes: 3
Views: 571
Reputation: 434
Several answers suggest an imperative approach which is considered an anti-pattern in BDD. Instead I strong suggest you follow the declarative approach with your Gherkin using natural or business language. If you are actually testing the login feature, I'd propose something like:
When an authorised user enters their credentials
or role based
When an Administrator is authorised
If login is actually a prerequisite for the feature under test then something such as:
Given an authorised user
or
Given an authorised Administrator
These can be backed up with a Credentials Manager.
... = ExpectedData.credentialsFor("@authorised");
The tag should represent the characteristics, not the identity of the expected data, to be retrieved from a test data db or csv containing something like:
@admin, administrator, password
@authorised, user, password
@unauthorised, user, wrong
The same approach should be used for all test data entry, such as:
Given a Cash Customer
Given a Credit Customer
Given a Customer with an overdue account
A strong benefit of this approach is the test suit can be readily reused on different environment by making the data/credential handler environment aware.
Upvotes: 2
Reputation: 4099
There are a couple of ways you could improve these steps and avoid the use of regex.
1) Have the user know its credentials and have the step ask the user for the credentials
So you would have
Given I am a user
@user = create_user # method creates a user with credentials
end
When `I enter the users credentials` do
fill_in username: @user.username
fill_in password: @user.password
end
When `I enter the wrong credentials for the user` do
fill_in username: @user.username
fill_in password: @user.bad_password # or perhaps just bad_password
end
this approach removes all the complexity from cucumber and places it in the helper methods you are calling to create a user.
2) Have more arguments for your step definition
When 'I enter the credentials user: (\\S+) password: (\\S+) do |username, password|
fill_in username: username
fill_in password: password
end
When 'I enter the bad credentials user: (\\S+) password: (\\S+) do |username, password|
fill_in username: username
fill_in password: password
end
I strongly prefer the first approach, you should keep features and scenarios super simple and push complexity down to code. Code is much better at dealing with complexity than Cucumber.
I've been cuking since before Cucumber was named, and now never use regex's or scenario outlines when I cuke. You don't need to either.
Upvotes: 2
Reputation: 1996
Please execute below step definitions and let us know if worked for you.
@When("^I enter the ([^\"]*) for the user$")
public void stepDefinition(String cred){
//code
}
@When("^I enter the correct ([^\"]*) for the user$")
public void otherStepDefinition(String cred){
//other code
}
Two metacharacters (^, $) are called anchors, because they’re used to tie down each end of the regular expression to the beginning and end of the string that they match on.
Upvotes: -1
Reputation: 626758
The first rule should be changed to
@When("I enter the (\\S+) for the user$")
Here, \S+
matches 1 or more non-whitespace characters. If there can be no non-whitespace chars use \S*
.
To match two "words" you may use
@When("I enter the (\\S+\\s+\\S+) for the user$")
Note that you may control the number of "words" using quantifiers, e.g. this will match 2 or 3 words:
@When("I enter the (\\S+(?:\\s+\\S+){1,2}) for the user$")
To match 2 or more words:
@When("I enter the (\\S+(?:\\s+\\S+){1,}) for the user$")
@When("I enter the (\\S+(?:\\s+\\S+)+) for the user$")
Upvotes: 2