How to write scenario outline to capture list of object in a single argument? - cucumber

When writing cucumber scenario outline test cases, sometimes i have requirement that i need one of the placeholder to hold a list of data instead of one. See below pseudo example:
Scenario Outline: example
Given I have <input_1>
When I choose <input_2>
Then I should receive <result_list> //instead of a single result
Examples:
| input_1 | input_2 | result |
| input_1_case_1 | input_2_case_1 | result_1_case_1_part_1 |
| | | result_1_case_1_part_2 |
| | | result_1_case_1_part_3 |
In the above example, my "result" need to capture a list of object for each single input_1 and input_2 parameter. But with the above writing, cucumber will not compile the last statement to something like:
#Then("....")
public void i_should_receive(Datatable or list of object) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
How can write my cucumber script to achieve what i want?
Thanks.

Scenario Outline: example
Given I have <input_1>
When I choose <input_2>
Then I should receive <result_list> //instead of a single result
Examples:
| input_1 | input_2 | result
| input_1_case_1 | input_2_case_1 | result_1_case_1_part_1,result_1_case_1_part_2,result_1_case_1_part_3 |
Then in your step definition
#Then("....")
public void i_should_receive(String result) throws Throwable {
List<String> items = Arrays.asList(str.split("\\s*,\\s*"));
}

I've been able to set a list of values in a cucumber example, this way:
Scenario Outline: The role already exists in the system, with the specified permissions
Given the user admin is logged in
And the role ADMIN with permissions <permissions> to be created
When a call to SecurityService is performed to create system roles
Then http status code 200 is returned
Examples:
|permissions |
|REGISTER_ACCOUNT,REVOKE_TOKENS,GET_ROLES,SET_ROLES|
And the concrete method:
#And("^the role ([^\"]*) with permissions ([^\"]*) to be created$")
public void theRoleWithPermissionsToBeCreated(String roleCode, List<String> permissions) {
for me, this works like a charm and I receive a list of Strings directly, without the need to parse a string value

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>".

Fetching all cucumber scenarios that have a particular tag

How can I fetch a list of all the scenarios that have a particular tag. For example
get all scenarios that have #checkout tag.
Lets assume you have 15-20 Scenarios/Scenarios Outline tagged with #checkout.
#checkout
Scenario Outline: Validation of UseCase Guest User Order Placement flow from Search
Given User is on Brand Home Page <Site>
And User searches for a styleId and makes product selection on the basis of given color and size
| Style_ID | Product_Size | Product_Color |
| TestData1 | TestData1 | TestData1 |
| TestData2 | TestData2 | TestData2 |
Then Clicking on Cart icon shall take user to Shopping Bag
Please follow this way to fetch name of scenarios.
File name Hook.java
#Before
public void setUpScenario(Scenario scenario){
String scenarioName = scenario.getName();
//Either you can write down name of the scenario under a file system like excel or implement in the way you want
}
Please lets know if you find it meaningful and it solved your problem.
Dry run to the rescue.
Dry run gives you a way to quickly scan your features without actually running them.
Try the following CucumberOptions annotations (this is Java/Junit version, but the idea applies everywhere)
#RunWith(Cucumber.class)
#CucumberOptions(plugin = { "pretty", "html:target/cucumber-html-report", "json:target/cucumber.json" }, glue = {
"some.stepdef" }, features = { "src/cucumberTest/featureFiles" }, tags = { "#now" }
,dryRun = true, strict=true)
public class CucumberNowTestDryRunner {
}
The cucumber report will look like this

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.

How can I get the Scenario Outline Examples' table?

In AfterScenario method, I want to get the rows from table "Examples" in Scenario Outline, to get the values in it, and search that specific values in the database
I know that this can be achieved by using Context.Scenario.Current...
Context.Scenario.Current[key]=value;
...but for some reason I'd like to be able to get it in a simpler way
like this:
ScenarioContext.Current.Examples();
----------- SCENARIO --------------------------------
Scenario Outline: Create a Matter
Given I create matter "< matterName >"
Examples:
| matterName |
| TAXABLE |
----------AFTER SCENARIO -----------------------------------
[AfterScenario()]
public void After()
{
string table = ScenarioContext.Current.Examples();
}
So if you look at the code for ScenarioContext you can see it inherits from SpecflowContext which is itself a Dictionary<string, object>. This means that you can simply use Values to get the collection of values, but I have no idea if they are Examples or not.
The best solution I came up with was to infer the examples by keeping my own static singleton object, then counting how many times the same scenario ran.
MyContext.Current.Counts[ScenarioContext.Current.ScenarioInfo.Title]++;
Of course, this doesn't work very well if you don't run all the tests at the same time or run them in random order. Having a table with the examples themselves would be more ideal, but if you combine my technique along with using ScenarioStepContext you could extract the parameters of the Examples table out of the rendered step definition text itself.
Feature
Scenario Outline: The system shall do something!
Given some input <input>
When something happens
Then something should have happened
Examples:
| input |
| 1 |
| 2 |
| 3 |
SpecFlow Hook
[BeforeStep]
public void BeforeStep()
{
var text = ScenarioStepContext.Current.StepInfo.Text;
var stepType = ScenarioStepContext.Current.StepInfo.StepDefinitionType;
if (text.StartsWith("some input ") && stepType == StepDefinitionType.Given)
{
var input = text.Split(' ').Last();
}
}

How do I create a Cucumber DataTable?

I want to manually set up a Cucumber DataTable using Java (instead of Gherkin).
In Gherkin, my table would look like this:
| h1 | h2 |
| v1 | v2 |
My Java so far looks like this:
List<String> raw = Arrays.asList( "v1", "v2");
DataTable dataTable = DataTable.create(raw, Locale.getDefault(), "h1", "h2");
What I get back is a DataTable with headers but no contents. It's also longer than expected:
| h1| h2 |
| | |
| | |
I'm sure the solution must be fairly simple, but I'm a bit at a loss right now. What do I need to do to get my table?
Hope this helps. If you're full Gherkins step looks like this...
When I see the following cooked I should say:
| food | say |
| Bacon | Yum! |
| Peas | Really? |
You want this in Java. (Note that the cucumber.api.DataTable passed in is setup with your expected values before the test).
#When("^I see the following cooked I should say:$")
public void theFoodResponse(DataTable expectedCucumberTable) {
// Normally you'd put this in a database or JSON
List<Cuke> actualCukes = new ArrayList();
actualCukes.add(new Cuke("Bacon", "Yum!"));
actualCukes.add(new Cuke("Peas", "Really?"));
Another link to a Full Example.diff(actualCukes)
}
I will say that in the examples by Aslak Hellesøy he doesn't actually use the DataTable.
He would do your example something like this:
#When("^I see the following cooked I should say:$")
public void theFoodResponse(List<Entry> entries) {
for (Entry entry : entries) {
// Test actual app you've written
hungryHuman.setInputValue(entry.food);
hungryHuman.setOutputValue(entry.say);
}
}
public class Entry {
String food;
String say;
}
For a Full Example for more reading check out:
Gherkins calculator: link
Java calculator Step Definitions: link
EDIT:
Sorry for the overkill #Christian, you perhaps didn't need the whole context of how to use it in an app, just a clean way to use DataTable.create and most of what I posted was another way to skin that cat with the Entry class (Which might be helpful for those reading this later.)
So the way you did it in your comment wasn't far off. I'm no pro at collections, so I can't give you any tips on making your 2D List of Strings, but I can clarify on the last two parameters (if you're using all 4).
If your columns are using Date or Calendar fields you can indicate a
Format in the second to last param.
If you don't use the
last one for Column Names, then it will automatically read your top line string for the column names.
Also you can drop the Locale.getDefault() and it will do that for you; so then you're looking at:
.
List<List<String>> infoInTheRaw = Arrays.asList( Arrays.asList("h1", "h2"),
Arrays.asList("v1", "v2") );
DataTable dataTable = DataTable.create(infoInTheRaw);
You could also use the constructor which would be equally messy. :)
Instead of DataTable we can actually create List of custom object using the same fields as in data table.
for e.g.
Then the book list response should contain records as
| book_id | book_title | book_cost |
| B0001 | Head First Java | 350|
| B002 | Head First Spring| 550|
Now your Step class should define a Step as
#Then("^the book list response should contain records as$")
public void validateBookRecords(List<Book> booksList) throws Throwable { //assertions will go here}
And your Book class should look like
public class Book {
public String book_id;
public String book_title;
public String book_cost;
}
Since the fields are all public so no getter/setter are needed. If you decide to declare them private (dont see a reason why) then ensure to add getters/setters as well.
Hope this helps
the cucumber dataTable can be build from nested lists where the first List in the nested lists contains the names of the columns and the others are the data lists per rows:
public static DataTable createTestDataTable() {
List<List<String>> dtList = new ArrayList<>();
List<String> columns = Arrays.asList("col1", "col2", "col3");
List<String> dataRow1 = Arrays.asList("r1c1", "r1c2", "r1c3");
List<String> dataRow2 = Arrays.asList("r2c1", "r2c2", "r2c3");
dtList.add(columns);
dtList.add(dataRow1);
dtList.add(dataRow2);
return DataTable.create(dtList);
}
This corresponds to:
|col1|col2|col3| <-- columns
|r1c1|r1c2|r1c3| <-- data row 1
|r2c1|r2c2|r2c3| <-- data row 2
this is the method that I use to extract the first row as a table headers from the Cucumber dataTabe object.
for this scenario:
When I do some stuff
| header1 | header2 | header3 | header4 |
| N | do | | |
| Nu | | some | stuff |
| qwerty | | some | stuff |
| cook | do | | |
this solution:
public void i_consume_datatable(DataTable table) {
//this is the little optimized version
List<List<String>> dataLists = table.asLists(String.class);
if (dataLists.size() > 1) {
String[] headers = dataLists.get(0).toArray(new String[0]);
dataLists.stream().skip(1).map(rowList -> {
Map<String, String> row = new LinkedHashMap<>();
IntStream.range(0, headers.length).forEach(i -> row.put(headers[i], rowList.get(i)));
return row;
}).forEach(map -> yourActualMethodWhichDoTheWork(map.get(“header1”), map.get("header2”), map.get("header3”), map.get("header4”)));
}
}

Resources