Thursday, August 2, 2018

Parameterization in Cucumber - Bean Objects

Another way to pass data table is through data table transformer to convert the data table to a list of bean object. You don't need to define data entry transformer in the previous version of Cucumber 3.0. But you have to do that if you use the latest version of Cucumber.

Here is the feature definition.

  Scenario: Login Failure
    Given User is on Home Page
    And Sign In link is displayed
    When User clicks the Sign In link
    And User enters Credentials to login
    | Username | Password|
    | username | password|
    | username1 | password1|
    Then User should be login failed message

And Bean definition.

package me.simplejavautomation.data;

public class Credentials {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}


Define and register table transformer.

package me.simplejavautomation.data.transformer;

import java.util.Locale;
import java.util.Map;

import cucumber.api.TypeRegistry;
import cucumber.api.TypeRegistryConfigurer;
import io.cucumber.datatable.DataTableType;
import io.cucumber.datatable.TableEntryTransformer;
import me.simplejavautomation.data.Credentials;

public class TypeRegistryConfiguration implements TypeRegistryConfigurer {

    @Override
    public Locale locale() {
        return Locale.ENGLISH;
    }

    @Override
    public void configureTypeRegistry(TypeRegistry typeRegistry) {
        typeRegistry.defineDataTableType(new DataTableType(Credentials.class,
                  new TableEntryTransformer<Credentials>() {

            @Override
            public Credentials transform(Map<String, String> entry)
                   throws Throwable {
                Credentials credentials = new Credentials();
                credentials.setUsername(entry.get("Username"));
                credentials.setPassword(entry.get("Password"));
                return credentials;
            }
        }));
    }
}


Add transformer package to CucumberOptions configuration

package me.simplejavautomation;

import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/features",
       glue = { "me.simplejavautomation.stepdefs",
        "me.simplejavautomation.data.transformer" })
public class CucumberTestRunner {

}

And then you are ready to go.

Parameterization in Cucumber - Data Tables

To pass a group of data to a single feature step, you can use Data Tables in Cucumber feature definition.

Scenario: Successful Login with Valid Credentials
    Given User is on Home Page
    When User Navigate to LogIn Page
    And User enters Credentials to LogIn
        | user1 | p2ssword |
        | user2 | p2ssword |
    Then Message displayed Login Successfully

Just use "|" mark to separate different column and each line as a table row.

@When("^User enters Credentials to LogIn$")
public void user_enters_credentials_to_login(DataTable credentials) {
    List<List<String>> data = credentials.asLists();
    driver.findElement(By.id("xv_username")).sendKeys(data.get(0).get(0));
    driver.findElement(By.id("header-myairnz-password")).sendKeys(data.get(0).get(1));
    driver.findElement(By.cssSelector("input[name='login']")).click();
}

When it is passed to step definition method at runtime, you may access this data table through DataTable parameter.


1) Data tables as List<List<String>>
     You can call "credentials.asLists();" to get a List<List<String>> object to access all the data in the data table, just like a two dimension array.

2) Data tables as List<Map<String, String>>
    Or you can call "credentials.asMaps() to get a List<Map<String, String>> object to access all the data in the data table, but make sure you have added a key row in the first row in the data table.

     | Username| Password|
     | user1 | p2ssword |
     | user2 | p2ssword |

    To access Map list,

List<Map<String, String>> data =  dataTable.asMaps();
username = data.get(0).get("Username");
password = data.get(0).get("Password");

Check the other interface in DataTable, you can find other ways you wanted.

Wednesday, August 1, 2018

Parameterization in Cucumber - Examples

Another way to pass test input to step definition method is using Examples keyword in Scenario Outline.


  Feature: Sign In

  Scenario Outline: Login Failure
    Given User is on Home Page
    And Sign In link is displayed
    When User clicks the Sign In link
    And User enters wrong "<username>" and "<password>"
    Then User should be login failed message

  Examples:
      | username  | password  |
      | username1 | password1 |
      | username2 | password2 |


The Cucumber runner will execute all the inputs in Examples table one by one in while scenario steps.

The step definition is the same as the last post.

Parameterization in Cucumber - Quotation

When feature step has been glued to step definition, there are several ways to pass parameters to step definition from features.

The first way is using quotation marks ("") in features.

  Feature: Sign In

  Scenario: Login Failure
    Given User is on Home Page
    And Sign In link is displayed
    When User clicks the Sign In link
    And User enters wrong "username" and "password"
    Then User should see the failed message


So the "username" and "password" will be passed to step definition method as parameters.

@When("User enters wrong \"(.*)\" and \"(.*)\"")
public void user_enters_wrong_username_and_password(String username, String password) {
...
}

Cucumber Options

To execute the Cucumber test, you have to configure features and glue to Cucumber runner.

package me.simplejavautomation;

import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/features",
    glue = { "me.simplejavautomation.stepdefs"})
public class CucumberTestRunner {

}

Here is the diagram of CucumberOptions annotation.

dryRun -- show steps if don't have step definition.
features -- the paths of feature files.
glue -- the classpath of step definition files.
tags -- specify which tags in feature files should be executed.
monochrome -- display console output in the much readable way.
plugin -- specify different formatting options for the output reports.
strict -- if strict mode is enabled (fail if there are undefined or pending steps).
name -- specify a pattern filter for features or scenarios
snippets -- what format should the snippets use. underscore, camelcase.
junit -- the options for the JUnit runner.