BDD: SpecFlow - Scenario Outline Behaviour Not As Expected - cucumber

Using scenario outlines in SpecFlow, e.g.
Scenario Outline: Invalid Login Details
Given some pre-conditions...
When user "Larry" enters username <username> and password <password>
Then the message "Invalid Login Details" should be displayed
Examples:
|username|password|
|larry06 | |
|larry06 |^&*%*^$ |
|%^&&** |pass123 |
| |pass123 |
I expected that the "When" step would be evaluated as such:
public void WhenUserEntersUsernameAndPassword(String username, String password){}
And that the scenario would be run 4 times - for each row of the table, passing the values as required. That's not the case.
Instead, SpecFlow creates 1 of 4 required step definitions:
[When(#"""(.*)"" provides the following new username larry(.*) and password ")]
public void WhenUserEntersUsernameLarryAndPassword(string p0, int p1)
{
//TODO
}
And to get the remaining 3 to 'work' I need to manually write methods explicitly matching other values in the table.
I've since realised that I can just say:
When "Larry" enters username "<username>" and password "<password>"
And I get:
[When(#"""(.*)"" provides the following ""(.*)"" and ""(.*)""")]
public void WhenUserEntersUsernameAndPassword(string p0, string name, string pass)
{
//TODO
}
Perfect.
But all documentation seems to suggest I don't need "" and that should just work (e.g. https://github.com/cucumber/cucumber/wiki/Scenario-outlines). I note:
"Your step definitions will never have to match a placeholder. They will need to match the values that will replace the placeholder"
I just don't really see the value of writing separate step definitions for each line of the table.
Is this nuance specific to SpecFlow?

When "Larry" enters username <username> and password <password>
will match
[When(#"""(.*)"" enters username (.*) and password (.*)")]
public void WhenEntersUsernameAndPassword(string p0, string name, string pass)
{
//TODO
}
so the documentation is fine.
The problem you experienced is that the auto generation of step text doesn't anticipate what regexs to insert without the "..." - which I guess it must be using as an indicator that you are passing interchangable strings - matchable with "(.*)", but if you don't want the quotes, you can still manually correct it just fine.

Related

Cucumber is not providing the method signatures for steps in the feature file

I'm trying to fill out the fields on this demo site: http://newtours.demoaut.com/mercuryregister.php
This is my feature file:
Feature: Testing Mercury Tours' register page
Background:
Given the user has launched their browser
And the browser is on Mercury Tour's register page
Scenario Outline: Testing Mercury Tours' registration page via positive testing
When the user enters the "<First Name>"
And enters the "<Last Name>"
And enters the "<Phone>"
And enters the "<Email>"
And enters the "<Address>"
And enters the "<City>"
And enters the "<State>"
And enters the "<Postal Code>"
And selects the "<Country>"
And enters the "<User Name>"
And enters the "<Password>"
And enters the "<Confirm Password>"
Examples:
| First Name | Last Name | Phone | Email | Address | City | State | Postal Code | Country | User Name | Password | Confirm Password |
| Bob | Mayer | 1-877-393-4448 | BobM#example.com | 123 Victory Lane | Beverly Hills | CA | 90210 | United States | BobM | 123password | 123password |
When I run this feature file, Cucumber gives me the method signatures for the first two steps (first name & last name) and the Select draw down menu (fpr country) but not the rest:
#When("^the user enters the \"([^\"]*)\"$")
public void the_user_enters_the(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^enters the \"([^\"]*)\"$")
public void enters_the(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^selects the \"([^\"]*)\"$")
public void selects_the(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
How do I implement methods to fill other text fields like phone #, email, and address?
The other "missing" steps match the same pattern - ^enters the \"([^\"]*)\"$ which is the second one. If u want cucumber to emit step definition method signatures for each step consider making them unique. Change And enters the "<Phone>" to something like And enters phone details - "<Phone>".

Mapping wrong number of parameter from Gherkin features file to step definition

I had feature declaration like this:
Feature: find taxi and minicabs information
in order to get taxi and minicabs contact at given location
as application developer
I want to find tax and minicabs contact information at given location or query options
Scenario Outline: find taxi and minicabs contact information
Given Joe at location with <lat> and <lon>
When get all taxi and minicabs contacts information
Then should see list of taxi and minicabs
And all of them are at location with <lat> and <lon>
Examples:
| lat | lon |
| 51.490075 | -0.133226 |
And I had step definition like this:
#Given("^Joe at location with ([+-]?([0-9]+[.])?[0-9]+) and ([+-]?([0-9]+[.])?[0-9]+)$")
public void joeAtLocationWithLatAndLon(Number lat, Number lon) throws Throwable {
....
}
I expected I can received 2 parameters but Cucumber passed to me 4 parameters.
Error message as below:
with pattern [^Joe at location with ([+-]?([0-9]+[.])?[0-9]+) and ([+-]?([0-9]+[.])?[0-9]+)$] is declared with 2 parameters. However, the gherkin step has 4 arguments [51.490075, 51., -0.133226, 0.].
Do you have any idea about this? btw, I very appreciate if you can explain the way cucumber identify the number of parameters or share me any document about that.
The issue is the two inside brackets inside the regular expression. Using the current regex you will get 2 groups - one the whole "51.490075" and second "51." which matches the exp in the ([0-9]+[.]) part. Thus 4 arguments are created.
Remove the inside brackets and you will get just one argument for each, so two in total.
The next problem you are going to have is cucumber does not know how to transform String to Number class unless you tell it. For this you need to make use of the Transform annotation and create a specific class for this.
import cucumber.api.Transformer;
public class NumberTransformer extends Transformer<Number>{
#Override
public Number transform(String value) {
return Double.parseDouble(value);
}
}
#Given("^Joe at location with ([+-]?[0-9]+[.]?[0-9]+) and ([+-]?[0-9]+[.]?[0-9]+)$")
public void joeAtLocationWithAnd(#Transform(NumberTransformer.class)Number arg1, #Transform(NumberTransformer.class)Number arg2) throws Exception {
System.out.println(arg1);
System.out.println(arg2);
}
For the transforming issue you can also look up xstreams. If you are using cucumber 2, these kind of transformation is easier by using Xstreamconvertor annotation - https://github.com/cucumber/cucumber-jvm/pull/1010

Range Attribute in MVC 5 not working as expected

I am learning MVC (version 5) by doing a sample project. Hence I am not using any scaffolding and doing everything from scratch. I have a View Model, which has a Password field with the following validations.
[Display(Name = "Password")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "{0} is Required.")]
[Range(1, 4, ErrorMessage = "{0} has to be between {1} and {2} characters.")]
public string Password { get; set; }
Now in my .cshtml, I have a password textbox rendered using #Html.EditorFor. Since I am learning, I don't have any css added. I have added references to jquery-1.10.2.js, jquery.validate.js and jquery.validate.unobstrusive.js in the cshtml file. The validations are working properly, except for the above password field. If I enter only 1 character in the password textbox, validation passes, whereas anything more than that fails, which is strange. I am not able to understand this. Can anyone please help me with this?
As you are using this as string please use below method
[StringLength(4, MinimumLength = 1, ErrorMessage = "{0} has to be between {1} and {2} characters.")]
What you have done is specified value in range so when you put 1 to 4 in the field its valid if you put 5 its not valid because it exceeds the range.
When you need length not the actual value you should use string length on property.
Hope this will solve the problem

Specflow: using same step definition for scenario and scenario outline

My feature file contains a 'scenario' test for a successful login and a 'Scenario Outline' test for testing multiple login details which should be unsuccessful.
#web
Scenario: Successful login
Given I have entered username 'tomsmith' and password 'SuperSecretPassword!' into the application
When I login
Then I should be informed that login was successful
#web
Scenario Outline: Unsuccessful login
Given I have entered username <username> and password <password> into the application
When I login
Then I should be informed that login was unsuccessful
Examples:
| testing | username | password |
| invalid combination 1 | test | test |
| special characters | $$$ | SuperSecretPassword! |
I would like both to use the same step definition (as they are just passing parameters)
My step definition is:
[Given(#"I have entered username '(.*)' and password '(.*)' into the application")]
public void GivenIHaveEnteredUsernameAndPasswordIntoTheApplication(string p0, string p1)
{
login = new LoginPage();
login.with(p0, p1);
}
The problem is that the scenario outline tests do not run, they return a 'Pending' error: Pending: No matching step definition found for one or more steps
and suggests the step definition should be:
[Given(#"I have entered test and test into the application")]
Can anyone help please?
you problem is on this line:
Given I have entered username <username> and password <password> into the application
it should be
Given I have entered username '<username>' and password '<password>' into the application
you just missed out the ' marks

Conditional Inputs?

I'm trying to write a cucumber test for part of our application (I'm completely new to cucumber, and writing acceptance tests really), and I have a step in the test, which I want to do one of 2 different things. I want it to either check for a specific value, or check for a system default value.
This is what I came up with
Scenario Outline: English News
Given with the locale is set to '<language>'
When a user views the page
Then they see the <image> image
Examples:
| language | image |
| en-gb | default |
| fr | "french.png" |
This then hits one of 2 different step definitions,
#And("^they see the default image$")
public void defaultImage() throws Throwable {
// check for system default
}
#And("^they see the \"(.*)\" image$")
public void customImage(String image) throws Throwable {
// check for specific value from the input
}
Is this the correct way to do this? My TL has suggested that I should actually only have the one step def, and pass "default" as the input, and then do a conditional check inside the step def, like this:
#And("^they see the \"(.*)\" image$")
public void checkImage(String image) throws Throwable {
if ("default".equals(image)){
// check for system default
} else {
// check for specific value from the input
}
}
Which is the correct way to do this? Any help is greatly appreciated.
your default image must have a real name, right ? so why not validating its real name ? because "default" could be anything so not everyone may understand the same thing.
If you do this, indeed you need only one step def. I wouldn't put an if check, I would assert the real name. You can maybe add a comment in your example table saying that the first value is the default, so that it's clear for everyone in your team.

Resources