How do I create a Cucumber DataTable? - cucumber

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”)));
}
}

Related

Parse Json Array in KQL

Json text isn't parsing in KQL correctly. I tried using parse_json as well but that didn't work either. I did confirm the extend AllProperties is holding the correct data.
DeviceInfo
| where RegistryDeviceTag == "Standard"
| extend AllProperties = todynamic(LoggedOnUsers)
| project DeviceName, Users = AllProperties["Username"]
Output gives me the correct DeviceName but doesn't give any data in the Username field.
(based on the sample input you provided in the comment)
if the array that is "LoggedOnUsers" includes exactly one entry, you can do this:
print input = '[{"UserName":"TheUserName","DomainName":"TheDomainName","Sid":"TheSID#"}]'
| project UserName = parse_json(input)[0].UserName
otherwise, you can use mv-expand or mv-apply:
print input = '[{"UserName":"TheUserName","DomainName":"TheDomainName","Sid":"TheSID#"}]'
| project parse_json(input)
| mv-apply input on (
project UserName = input.UserName
)

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

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

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

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();
}
}

Java Cucumber Step Definition for vertical DataTable

I'm using cucumber-jvm. I have the following in a .feature file:
Background:
Given the following account file line:
| First Name | Lance |
| Last Name | Fisher |
| Corporate Name | |
This is a vertically-oriented table. The following generated step definition uses First Name and Lance as the headers, where First Name, Last Name, and Corporate Name should be the headers.
#Given("^the following account file line:$")
public void the_following_account_file_line(DataTable arg1) throws Throwable {
// Express the Regexp above with the code you wish you had
// For automatic conversion, change DataTable to List<YourType>
throw new PendingException();
}
How would I implement a step definition to handle a vertical table rather than a horizontal table?
Just receive the value on parameter as Map<String, String> instead of DataTable. Cucumber will convert the first columns as map keys and the second column as map values.
It's simple enough, as the Datatable can return an array of arrays of strings, and you can step through this in whatever manner you wish.
However, I'd agree with Prakash Murthy that the horizontal table is more usual and useable.

Resources