Thursday, February 4, 2016

DataTable On Cucumber JVM

We need to supply different data on different field or we need to pass the parameter on different variable for some certain situation. We can handle this scenario in Cucumber-JVM very easily using DataTable. Whenever we want to use DataTable concept we need to write our feature file looks like below:

Feature: This is a sample feature file

Scenario: This is a scenario to test DataTable on Cucumber JVM.
Given scenario data
When executed from Runner Class
Then UserName and Password Like below.
| userName | password |
| TestUser1 | TestPassword1 |
| TestUser2 | TestPassword2 |

Here we can see that some username and password data available on tabular form,actually what happen if we run our glue code corresponding to this feature file Scenario will be executed only once but executed with list of data.

So it will be more clear if we go through our glue code:

import cucumber.api.DataTable;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class SumFeatureTest {

@Given("^scenario data$")
public void scenarioData() throws Throwable {
System.out.println("Scenario Have Some Data");
}

@When("^executed from Runner Class$")
public void executedFromRunnerClass() throws Throwable {
System.out.println("Executed From Runner Class");
}

@Then("^UserName and Password Like below\\.$")
public void usernameAndPasswordLikeBelow(DataTable dataTable) throws Throwable {
   // Write code here that turns the phrase above into concrete actions
   // For automatic transformation, change DataTable to one of
   // List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
   // E,K,V must be a scalar (String, Integer, Date, enum etc)

System.out.println(dataTable.asMap(String.class, String.class));
System.out.println(dataTable.asMaps(String.class, String.class));
  System.out.println(dataTable.asList(UserDetailsDTO.class).get(0).getUserName()+ " "                                                 +dataTable.asList(UserDetailsDTO.class).get(0).getPassword());
}
}

So if we observe our code then we find that we use DataTable on different way.

  • We convert DataTable asMap where Map holds keys as the first column of this table and second column is representing the value of this Map so key value pair looks like : userName=password, TestUser1=TestPassword1, TestUser2=TestPassword2
  • We convert DataTable asMaps where it returns list of Map.Map holds keys as the first row of this table and other rows is representing the value of this Map so key value pair looks like :{userName=TestUser1, password=TestPassword1}, {userName=TestUser2, password=TestPassword2}
  • We convert DataTable asList where it returns the list of Table Object. So now question be in mind how we create this Table object ? We create a class which holds variables and get setter methods, variable name of this class is same as column header name.
So our class should be looks like that :

public class UserDetailsDTO {
private String userName;
private String password;

public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPasword(String password) {
this.password = password;
}
}

We can get a extra facility of using a DTO object that is,our Table which is available on feature file can contains more than two columns.

Our Runner Class looks like below:

import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.SnippetType;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(
plugin = { 
"html:target/cucumber-html-report",
"json:target/cucumber.json", 
"pretty:target/cucumber-pretty.txt",
"usage:target/cucumber-usage.json",
"junit:target/cucumber-results.xml",
"progress:target/cucumber-progress.txt"
        },features ={"./sample.feature"},
glue ={"com/automation/steps"},strict = true,
dryRun= false,monochrome = true, snippets= SnippetType.CAMELCASE)

public class Runner {
}