Saturday, October 7, 2017

RealTime Report On Selenium WebDriver + TestNG

This is becoming an emerging need to have a compact and catchy Test Report after execution of the Tests. But what about if you will have the same compactness of the report at the Test Run Time?

Yes you can, if we expect to get a report in the middle of the execution you can implement this RealTimeReport to your project.


All the expectations below can be achieved through this:

  1. Get test report at Run Time - don't need to wait till end of the test execution.
  2. Only adding our pre-defined listener in user's testng.xml file can generate this report. So, NO need to change code. As an added benefit - you can implement this report in your existing project without making any change in your code.


It is very easy to use we need to follow the below steps :

Step 1:

We need to copy the below mentioned 5 packages under the src folder.


Step 2:

Copy the below folder and keep this folder under the root of the project.


Step 3:

Now add following to your testng.xml file
<listeners>
    <listener class-name="report.realtime.listener.RealTimeTestResultListener" />
</listeners>

Step 4:
 Now execute test using testng.xml file.

Step 5:

 After starts the execution RealtimeReport directory will be created under the root of the project and generate the beautiful report along with the execution status. 

Monday, May 29, 2017

Selenium WebDriver With Arquillian + Drone + Graphene

Still now we learn lots of thing in Selenium WebDriver and manage everything with our self. But now in open source era some framework is already in market which makes our life more simple, like Graphene.

Though Drone already integrate Selenium Webdriver within it, but Graphene makes our life more easy to deals with Selenium WebDriver.

Actually Arquillian is top on Drone and Graphene .

So In brief

 Arquillian : It is a testing framework, simply an extension to JUnit/TestNG frameworks.
 Drone : Drone takes care of Selenium WebDriver instance creation and configuration.
 Graphene : It is a wrapper around Selenium WebDriver with utilities class.

Arquillian can run in 2 different ways
  1. Container : It is mainly used for integration testing from development perspective. It maintains the container state and deployed the whole application then run this application with in a container.
  2. Standalone/Client : It is mainly used for automation of functional testing. Here application is not deployed with in a container.
We can store all test related configuration in arquillian.xml file. We can handle different type of wait very easily using Graphene.

We will know in later posts how to configure and learn in details about it for Standalone/Client mode.

Saturday, April 1, 2017

Loading Data From External File To Feature File Using Cucumber - JVM

On previous post we learn how to read data from external file using mentioning the Row number in feature file. Now we load data in feature file from external data source file before start to execute testable features.

We need to override the feature file with data from external data source(excel, csv etc) before executing the feature file. So if we want to do that we need to follow the below steps :

Step 1: 

We need to put tag on feature file because our parser need to understand where it will put the data within the feature file. That's why we specify the tag in feature file in the below pattern

##@externaldata@Excel file Location@SheetName

e.g ##@externaldata@./src/test/resources/TestData.xlsx@Sheet1

Step 2:

Read Excel file and store it List<Map<String columnName, String columnvalue>> .

Step 3: 

Write a parser to copy all the data from specified excel sheet to feature file.

Step 4:

Create custom Annotation because we need to copy all data from excel file to feature file before start to execute.

Step 5:

Create custom cucumber runner because we need to control cucumber runner to run our custom annotation at first.

Step 6 :
Create Runner and use custom runner from there.

So Complete code given below :

pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.blogspot.startingwithseleniumwebdriver</groupId>
    <artifactId>CucumberFeatureModification</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>5.5.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>5.5.0</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>
</project>


Our Feature :

Feature: This is a sample feature file

  Background:
    Given scenario data

  Scenario Outline: This is a scenario to test datadriven test on Cucumber JVM.
    When executed from Runner Class.
    Then UserName and Password shows on console from Examples "<UserName>" and "<Password>".

    Examples:
      | UserName | Password |
          ##@externaldata@./src/test/resources/data/TestData.xlsx@Sheet1


  Scenario: This is a scenario to test datatable test on Cucumber JVM.
    Then UserName and Password shows on console from datatable.
      | UserName | Password |
      ##@externaldata@./src/test/resources/data/TestData.xlsx@Sheet2


Excel reader : 

package com.automation.cucumber.helper;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.NumberToTextConverter;

public class ExcelReader {

    public List<Map<String, String>> getData(String excelFilePath, String sheetName)
            throws InvalidFormatException, IOException {
        Sheet sheet = getSheetByName(excelFilePath, sheetName);
        return readSheet(sheet);
    }

    public List<Map<String, String>> getData(String excelFilePath, int sheetNumber)
            throws InvalidFormatException, IOException {
        Sheet sheet = getSheetByIndex(excelFilePath, sheetNumber);
        return readSheet(sheet);
    }

    private Sheet getSheetByName(String excelFilePath, String sheetName) throws IOException, InvalidFormatException {
        Sheet sheet = getWorkBook(excelFilePath).getSheet(sheetName);
        return sheet;
    }

    private Sheet getSheetByIndex(String excelFilePath, int sheetNumber) throws IOException, InvalidFormatException {
        Sheet sheet = getWorkBook(excelFilePath).getSheetAt(sheetNumber);
        return sheet;
    }

    private Workbook getWorkBook(String excelFilePath) throws IOException, InvalidFormatException {
        return WorkbookFactory.create(new File(excelFilePath));
    }

    private List<Map<String, String>> readSheet(Sheet sheet) {
        Row row;
        int totalRow = sheet.getPhysicalNumberOfRows();
        List<Map<String, String>> excelRows = new ArrayList<Map<String, String>>();
        int headerRowNumber = getHeaderRowNumber(sheet);
        if (headerRowNumber != -1) {
            int totalColumn = sheet.getRow(headerRowNumber).getLastCellNum();
            int setCurrentRow = 1;
            for (int currentRow = setCurrentRow; currentRow <= totalRow; currentRow++) {
                row = getRow(sheet, sheet.getFirstRowNum() + currentRow);
                LinkedHashMap<String, String> columnMapdata = new LinkedHashMap<String, String>();
                for (int currentColumn = 0; currentColumn < totalColumn; currentColumn++) {
                    columnMapdata.putAll(getCellValue(sheet, row, currentColumn));
                }
                excelRows.add(columnMapdata);
            }
        }
        return excelRows;
    }


    private int getHeaderRowNumber(Sheet sheet) {
        Row row;
        int totalRow = sheet.getLastRowNum();
        for (int currentRow = 0; currentRow <= totalRow + 1; currentRow++) {
            row = getRow(sheet, currentRow);
            if (row != null) {
                int totalColumn = row.getLastCellNum();
                for (int currentColumn = 0; currentColumn < totalColumn; currentColumn++) {
                    Cell cell;
                    cell = row.getCell(currentColumn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                    if (cell.getCellType() == CellType.STRING) {
                        return row.getRowNum();

                    } else if (cell.getCellType() == CellType.NUMERIC) {
                        return row.getRowNum();

                    } else if (cell.getCellType() == CellType.BOOLEAN) {
                        return row.getRowNum();
                    } else if (cell.getCellType() == CellType.ERROR) {
                        return row.getRowNum();
                    }
                }
            }
        }
        return (-1);
    }

    private Row getRow(Sheet sheet, int rowNumber) {
        return sheet.getRow(rowNumber);
    }

    private LinkedHashMap<String, String> getCellValue(Sheet sheet, Row row, int currentColumn) {
        LinkedHashMap<String, String> columnMapdata = new LinkedHashMap<String, String>();
        Cell cell;
        if (row == null) {
            if (sheet.getRow(sheet.getFirstRowNum()).getCell(currentColumn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)
                    .getCellType() != CellType.BLANK) {
                String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(currentColumn)
                        .getStringCellValue();
                columnMapdata.put(columnHeaderName, "");
            }
        } else {
            cell = row.getCell(currentColumn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
            if (cell.getCellType() == CellType.STRING) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getCellType() != CellType.BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex()).getStringCellValue();
                    columnMapdata.put(columnHeaderName, cell.getStringCellValue());
                }
            } else if (cell.getCellType() == CellType.NUMERIC) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getCellType() != CellType.BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex()).getStringCellValue();
                    columnMapdata.put(columnHeaderName, NumberToTextConverter.toText(cell.getNumericCellValue()));
                }
            } else if (cell.getCellType() == CellType.BLANK) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getCellType() != CellType.BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex()).getStringCellValue();
                    columnMapdata.put(columnHeaderName, "");
                }
            } else if (cell.getCellType() == CellType.BOOLEAN) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getCellType() != CellType.BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex()).getStringCellValue();
                    columnMapdata.put(columnHeaderName, Boolean.toString(cell.getBooleanCellValue()));
                }
            } else if (cell.getCellType() == CellType.ERROR) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getCellType() != CellType.BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex()).getStringCellValue();
                    columnMapdata.put(columnHeaderName, Byte.toString(cell.getErrorCellValue()));
                }
            }
        }
        return columnMapdata;
    }
}

 

Parser To Copy Data From Excel

package com.automation.cucumber.helper;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

public class FeatureOverright {

    private static List<String> setExcelDataToFeature(File featureFile)
            throws InvalidFormatException, IOException {
        List<String> fileData = new ArrayList<String>();
        try (BufferedReader buffReader = new BufferedReader(
                new InputStreamReader(new BufferedInputStream(new FileInputStream(featureFile)), "UTF-8"))) {
            String data;
            List<Map<String, String>> excelData = null;
            boolean foundHashTag = false;
            boolean featureData = false;
            while ((data = buffReader.readLine()) != null) {
                String sheetName = null;
                String excelFilePath = null;
                if (data.trim().contains("##@externaldata")) {
                    excelFilePath = data.substring(StringUtils.ordinalIndexOf(data, "@", 2)+1, data.lastIndexOf("@"));
                    sheetName = data.substring(data.lastIndexOf("@")+1, data.length());
                    foundHashTag = true;
                    fileData.add(data);
                } if (foundHashTag) {
                    excelData = new ExcelReader().getData(excelFilePath, sheetName);
//                    String columnHeader = "";

//                    for (Entry<String, String> map : excelData.get(0).entrySet()) {
//                        columnHeader = columnHeader + "|" + map.getKey();
//                    }
//                  
//                    fileData.add(columnHeader + "|");

                    for (int rowNumber = 0; rowNumber < excelData.size()-1; rowNumber++) {
                        String cellData = "";
                        for (Entry<String, String> mapData : excelData.get(rowNumber).entrySet()) {
                            cellData = cellData + "|" + mapData.getValue();
                        }
                        fileData.add(cellData + "|");
                    }
                    foundHashTag = false;
                    featureData = true;
                    continue;
                }
                if(data.startsWith("|")||data.endsWith("|")){
                    if(featureData){
                        continue;
                    } else{
                        fileData.add(data);
                        continue;
                    }
                } else {
                    featureData = false;
                }
                fileData.add(data);
            }
        }
        return fileData;
    }

    private static List<File> listOfFeatureFiles(File folder) {
        List<File> featureFiles = new ArrayList<File>();
        for (File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                featureFiles.addAll(listOfFeatureFiles(fileEntry));
            } else {
                if (fileEntry.isFile() && fileEntry.getName().endsWith(".feature")) {
                    featureFiles.add(fileEntry);
                }
            }
        }
        return featureFiles;
    }

    public static void overrideFeatureFiles(String featuresDirectoryPath)
            throws IOException, InvalidFormatException {
        List<File> listOfFeatureFiles = listOfFeatureFiles(new File(featuresDirectoryPath));
        for (File featureFile : listOfFeatureFiles) {
            List<String> featureWithExcelData = setExcelDataToFeature(featureFile);
            try (BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(new FileOutputStream(featureFile), "UTF-8"));) {
                for (String string : featureWithExcelData) {
                    writer.write(string);
                    writer.write("\n");
                }
            }
        }
    }
}

 

Custom Annotation :

package com.automation.cucumber.helper;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface BeforeSuite {

}


Custom Runner :

package com.automation.cucumber.runner;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;

import com.automation.cucumber.helper.BeforeSuite;
import cucumber.api.junit.Cucumber;


public class CustomCucumberRunner extends Runner {

    private Class<Cucumber> classValue;
    private Cucumber cucumber;

    public CustomCucumberRunner(Class<Cucumber> classValue) throws Exception {
        this.classValue = classValue;
        cucumber = new Cucumber(classValue);
    }

    @Override
    public Description getDescription() {
        return cucumber.getDescription();
    }

    private void runAnnotatedMethods(Class<?> annotation) throws Exception {
        if (!annotation.isAnnotation()) {
            return;
        }
        Method[] methods = this.classValue.getMethods();
        for (Method method : methods) {
            Annotation[] annotations = method.getAnnotations();
            for (Annotation item : annotations) {
                if (item.annotationType().equals(annotation)) {
                    method.invoke(null);
                    break;
                }
            }
        }
    }

    @Override
    public void run(RunNotifier notifier) {
        try {
            runAnnotatedMethods(BeforeSuite.class);
            cucumber = new Cucumber(classValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
        cucumber.run(notifier);
    }
}

Cucumber Runner :

package com.automation.cucumber.runner;

import java.io.IOException;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.junit.runner.RunWith;

import com.automation.cucumber.helper.BeforeSuite;
import com.automation.cucumber.helper.FeatureOverright;

import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.CucumberOptions.SnippetType;

@CucumberOptions(plugin = { "html:target/cucumber-html-report", "json:target/cucumber.json" },
                features = {"src/test/resources/features" },
                glue = {"com/automation/cucumber/steps" },
                monochrome = true, snippets = SnippetType.CAMELCASE)

@RunWith(CustomCucumberRunner.class)
public class CucumberRunnerTest {
    @BeforeSuite
    public static void test() throws InvalidFormatException, IOException {
        FeatureOverright.overrideFeatureFiles(System.getProperty("user.dir")+"/src/test/resources/features");
    }
}


Step class : 
package com.automation.cucumber.steps;

import cucumber.api.DataTable;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class TestSteps {
   
    @Given("scenario data")
    public void scenario_data() {
        System.out.println("Scenario Have Some Data");
    }

    @When("executed from Runner Class.")
    public void executed_from_Runner_Class() {
        System.out.println("Executed From Runner Class");
    }

    @Then("UserName and Password shows on console from Examples {string} and {string}.")
    public void username_and_Password_shows_on_console_from_Examples_and(String userName, String password) {
        System.out.println("UserName : " + userName + " Password : " + password);
    }

    @Then("UserName and Password shows on console from datatable.")
    public void username_and_Password_shows_on_console_from_datatable(DataTable dataTable) {
        System.out.println("Data Table UserName : " + dataTable.asLists().get(1).get(0) + " Password : " + dataTable.asLists().get(1).get(1));
        System.out.println("Data Table UserName : " + dataTable.asList().get(2) + " Password : " + dataTable.asList().get(3));
        System.out.println("Data Table UserName : " + dataTable.asMaps().get(0).get("UserName") + " Password : " + dataTable.asMaps().get(0).get("Password"));
        System.out.println("Data Table UserName : " + dataTable.asMaps(String.class, String.class).get(0).get("UserName") + " Password : " + dataTable.asMaps(String.class, String.class).get(0).get("Password"));
    }
}

Getting Data From External File Using Cucumber - JVM

Cucumber facilitates us to make our Scenario as data driven if we change it to Scenario Outline with Example. But still there is a constraint on this, user not able to feed any external file within it.

So now we learn how to feed data from external excel file. There are 2 ways to make our Cucumber feature file have ability to load the data from external excel file.

  1. Providing numeric Row number in Example part of  Scenario Outline.
  2. Update the feature file with external data before start to to execute the Scenarios.
Here we learn the first option and next one we will learn later.

Step 1 :

Create  feature file and mention the row number of external excel file in Example section of Scenario Outline.

Feature: This is a sample feature file

  Scenario Outline: This is a scenario to test datadriven test on Cucumber JVM.
    Given scenario data
    When executed from Runner Class
    Then UserName and Password shows on console form given <RowsNumber>.

    Examples:
      | RowsNumber |
      |          1             |
      |          2            
|

Step 2 :

Generate glue code or step file.

public class TestSteps {
    @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 shows on console form given (\\d+)\\.$")
    public void usernameAndPasswordShowsOnConsoleFormGiven(int rowNumber) throws Throwable {
        ExcelReader externalData = new ExcelReader();
        List<Map<String, String>> testData = externalData.getData("./resources/TestData.xlsx", 0);
        System.out.println("UserName : " + testData.get(rowNumber).get("UserName") + " Password : " + testData.get(rowNumber).get("Password"));
    }

}  


Now  if we drill down this code, we can understand what happen with this row number which is specified in our feature file.

In the last method we return our excel file, then we pass the row number and pickup our desired column after passing the column name on map.

Step 3 :

So let's create this excel reader class :

 public class ExcelReader {

    public List<Map<String, String>> getData(String excelFilePath, String sheetName)
            throws InvalidFormatException, IOException {
        Sheet sheet = getSheetByName(excelFilePath, sheetName);
        return readSheet(sheet);
    }

    public List<Map<String, String>> getData(String excelFilePath, int sheetNumber)
            throws InvalidFormatException, IOException {
        Sheet sheet = getSheetByIndex(excelFilePath, sheetNumber);
        return readSheet(sheet);
    }

    private Sheet getSheetByName(String excelFilePath, String sheetName) throws IOException, InvalidFormatException {
        Sheet sheet = getWorkBook(excelFilePath).getSheet(sheetName);
        return sheet;
    }

    private Sheet getSheetByIndex(String excelFilePath, int sheetNumber) throws IOException, InvalidFormatException {
        Sheet sheet = getWorkBook(excelFilePath).getSheetAt(sheetNumber);
        return sheet;
    }

    private Workbook getWorkBook(String excelFilePath) throws IOException, InvalidFormatException {
        return WorkbookFactory.create(new File(excelFilePath));
    }

    private List<Map<String, String>> readSheet(Sheet sheet) {
        Row row;
        int totalRow = sheet.getPhysicalNumberOfRows();
        List<Map<String, String>> excelRows = new ArrayList<Map<String, String>>();
        int headerRowNumber = getHeaderRowNumber(sheet);
        if (headerRowNumber != -1) {
            int totalColumn = sheet.getRow(headerRowNumber).getLastCellNum();
            int setCurrentRow = 0;
            if(sheet instanceof HSSFSheet){
                setCurrentRow = 1;
            }
            for (int currentRow = setCurrentRow; currentRow <= totalRow; currentRow++) {
                row = getRow(sheet, sheet.getFirstRowNum() + currentRow);
                LinkedHashMap<String, String> columnMapdata = new LinkedHashMap<String, String>();
                for (int currentColumn = 0; currentColumn < totalColumn; currentColumn++) {
                    columnMapdata.putAll(getCellValue(sheet, row, currentColumn));
                }
                excelRows.add(columnMapdata);
            }
        }
        return excelRows;
    }


    private int getHeaderRowNumber(Sheet sheet) {
        Row row;
        int totalRow = sheet.getLastRowNum();
        for (int currentRow = 0; currentRow <= totalRow + 1; currentRow++) {
            row = getRow(sheet, currentRow);
            if (row != null) {
                int totalColumn = row.getLastCellNum();
                for (int currentColumn = 0; currentColumn < totalColumn; currentColumn++) {
                    Cell cell;
                    cell = row.getCell(currentColumn, Row.CREATE_NULL_AS_BLANK);
                    if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                        return row.getRowNum();

                    } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                        return row.getRowNum();

                    }
                    else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
                        return row.getRowNum();
                    } else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
                        return row.getRowNum();
                    }
                }
            }
        }
        return (-1);
    }

    private Row getRow(Sheet sheet, int rowNumber) {
        return sheet.getRow(rowNumber);
    }

    private LinkedHashMap<String, String> getCellValue(Sheet sheet, Row row, int currentColumn) {
        LinkedHashMap<String, String> columnMapdata = new LinkedHashMap<String, String>();
        Cell cell;
        if (row == null) {
            if (sheet.getRow(sheet.getFirstRowNum()).getCell(currentColumn, Row.CREATE_NULL_AS_BLANK)
                    .getCellType() != Cell.CELL_TYPE_BLANK) {
                String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(currentColumn)
                        .getStringCellValue();
                columnMapdata.put(columnHeaderName, "");
            }
        } else {
            cell = row.getCell(currentColumn, Row.CREATE_NULL_AS_BLANK);
            if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.CREATE_NULL_AS_BLANK)
                        .getCellType() != Cell.CELL_TYPE_BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex())
                            .getStringCellValue();
                    columnMapdata.put(columnHeaderName, cell.getStringCellValue());
                }
            } else if (cell.getCellTypeEnum() == CellType.NUMERIC) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.CREATE_NULL_AS_BLANK)
                        .getCellType() != Cell.CELL_TYPE_BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex())
                            .getStringCellValue();
                    columnMapdata.put(columnHeaderName, NumberToTextConverter.toText(cell.getNumericCellValue()));
                }
            } else if (cell.getCellType() == CellType.BLANK.getCode()) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.CREATE_NULL_AS_BLANK)
                        .getCellType() != Cell.CELL_TYPE_BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex())
                            .getStringCellValue();
                    columnMapdata.put(columnHeaderName, "");
                }
            } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.CREATE_NULL_AS_BLANK)
                        .getCellType() != Cell.CELL_TYPE_BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex())
                            .getStringCellValue();
                    columnMapdata.put(columnHeaderName, Boolean.toString(cell.getBooleanCellValue()));
                }
            } else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
                if (sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex(), Row.CREATE_NULL_AS_BLANK)
                        .getCellType() != Cell.CELL_TYPE_BLANK) {
                    String columnHeaderName = sheet.getRow(sheet.getFirstRowNum()).getCell(cell.getColumnIndex())
                            .getStringCellValue();
                    columnMapdata.put(columnHeaderName, Byte.toString(cell.getErrorCellValue()));
                }
            }
        }
        return columnMapdata;
    }
}


Step 4 : 

At last we need a runner class to run our cucumber project.

@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 ={"./resources/sample.feature"},
   glue ={"com/automation/cucumber/steps"},strict = true,
   dryRun= false,monochrome = true, snippets= SnippetType.CAMELCASE)
public class CucumberRunner {



Output : 

Scenario Have Some Data
Executed From Runner Class
UserName : Test UserName 1 Password : Test Password 1
Scenario Have Some Data
Executed From Runner Class
UserName : Test UserName 2 Password : Test Password 2

2 Scenarios (2 passed)
6 Steps (6 passed)
0m1.312s 

Sunday, December 25, 2016

How To Get Feature Name And Scenario Name Using Cucumber-JVM

Sometime we need to know the Feature name or Scenario name whenever we ran our script using Cucumber-JVM. It may be required for logging purpose for status of execution. So How we can do that. It is very simple we need to add the following lines to get the Feature Name and Scenario Name.

"Feature Name : " +  scenario.getId().split(";")[0]
"Scenario Name : " + scenario.getName()

Wednesday, November 30, 2016

How to Pass Examples Data As An Object In A Step Method Using Cucumber JVM

Still now whenever we use Scenario Outline we need to pass all parameters in a step method those are mentioned in glue code. So problem is if Examples section of Scenario Outline holds more parameters and also if our steps in feature file holds all the parameters then method argument count should be increased.

Now if we pass all parameters as a object then it becomes a single parameter on step method even if our feature steps holds lots of parameters. But there is a trick to make all this parameters as an object in step methods those are mentioned in feature steps.

So basically we mentioned our Example data to the feature step as Data Table.

So as an example :

Feature: This is a sample feature file

  Scenario Outline: This is a scenario to test datadriven test on Cucumber JVM.
    Given scenario data
    When executed from Runner Class.
    Then UserName and Password shows on console from Examples "<username>" and "<password>"
    Then UserName and Password shows on console with header as:
      | username     | password     |
      | "<username>" | "<password>" |
    Then UserName and Password shows on console without header as:
      | "<username>" | "<password>" |

    Examples: 
      | username        | password        |
      | Test UserName 1 | Test Password 1 |
      | Test UserName 2 | Test Password 2 |

So Glue Code is 

@Then("^UserName and Password shows on console from Examples \"([^\"]*)\" and \"([^\"]*)\"$")
public void usernameAndPasswordShowsOnConsoleFromExamplesAnd(String userName, String password) throws Throwable {
System.out.println("UserName : " + userName + " Password : " + password);
}

@Then("^UserName and Password shows on console with header as:$")
public void usernameAndPasswordShowsOnConsoleWithHeaderAs(List<ExampleData> data) throws Throwable {
System.out.println("UserName : " + data.get(0).getUsername() + " Password : " + data.get(0).getPassword());
}

@Then("^UserName and Password shows on console without header as:$")
public void usernameAndPasswordShowsOnConsoleWithoutHeaderAs(List<String> stringData) throws Throwable {
System.out.println("UserName : " + stringData.get(0) + " Password : " + stringData.get(1));
}

class ExampleData{
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 setPassword(String password) {
this.password = password;
}


}

 So if we drill down our code we can observe that when we mentioned the header of Examples below the feature steps we need to Create data object class in glue code to use it.

If user don't want to create any dataclass for that then user cannot mention the header name below the steps.



  

Sunday, October 9, 2016

Passing Parameter In Maven

Maven also provide us the facility to pass parameter at runtime and we can use this property value from our Java code.

There  are several way to get properties value from maven. Here we will learn how to retrieve the System property value from maven.

We use "maven-surefire-plugin" to set System Property from pom.xml and then it is very easy to retrieve system property using java.

So our sample pom.xml is looks like below :

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<systemPropertyVariables>
<testproperty>tetsproppertyValue</testproperty>
</systemPropertyVariables>
</configuration>
</plugin>
Sample code example :
public class TestLocalRepoTest {

@Test
public void sampleTest(){
System.out.println("Test System Property Property Value From Maven :"+ System.getProperty("testproperty"));
}
}

if we want to run this main class from maven we need to type this command

test

We can also access the System Properties if we run the main java class from maven. Then we need to use "exec-maven-plugin" to set the System Propertiey

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${exec.mainClass}</mainClass>
<systemProperties>
<systemProperty>
<key>testproperty</key>
<value>tetsproppertyValue</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>

Sample code example :
public class TestLocalRepo {

public static void main(String[] args) {
System.out.println("Test System Property Property Value From Maven :" + System.getProperty("testproperty"));
}
}

if we want to run this main class from maven we need to type this command
exec:java  -Dexec.mainClass="com.automation.example.TestLocalRepo"

Sunday, September 25, 2016

Adding External Jar In Maven Project

We know that maven is a build management tool. So when ever we need to add any jar for our project we can mention dependencies in POM(Project Object Model) file(xml file) then it automatically pull the jar from remote repository(default Apache Maven repository) and store it in default location(C:\Documents and Settings\User\.m2) if it is not available under this location.

But what happen if this jar is not available on remote server, but we need this jar to run our project. As well as we have no permission to upload this jar in any maven repository due to some security or restriction.

So maven provide us different way here we discuss two ways:
  1. Add jar in System Property.
  2. Use jar as project specific local Repository.
1. Add jar in System Property

For this we need to mention the path of this jar under <systemPath> tag and mention system under <scope> tag.

e.g :

<dependency>
    <groupId>group id name</groupId>
    <artifactId>artifact name</artifactId>
    <version>version number</version>
    <scope>system</scope>
    <systemPath>jar location</systemPath>
</dependency>


2. Use jar as project specific local Repository

For this we need to create a specific folder structure in our project as given below



and mention the repository path under <url> tag like file://${project.basedir}/lib
e.g :
        <dependency>
            <groupId>seleniumserver</groupId>
            <artifactId>seleniumserver-sdk</artifactId>
            <version>2.53.0</version>
        </dependency>
        <dependency>
            <groupId>seleniumclient</groupId>
            <artifactId>seleniumclient-sdk</artifactId>
            <version>2.53.0</version>
        </dependency>



    <repositories>
    <repository>
        <id>in-project</id>
        <name>In Project Repo</name>
        <url>file://${project.basedir}/lib</url>
    </repository>
    </repositories>


 




Tuesday, August 16, 2016

Running VBScript from Java

Some time we may require to run vbscript from java application. It is mainly required when we try play with system. So sample code is given below how to call vbscript file from java application.

public class TestVBScript {

    public static void main(String[] args) throws IOException {
        try {
            System.out.println(new File("a.vbs").getAbsolutePath());
            Runtime.getRuntime().exec("wscript.exe " + new File("samplevbs.vbs").getAbsolutePath());

        } catch (IOException ex) {

        }
    }
}

Saturday, July 16, 2016

Running batch file from Java

One of the most important requirement for batch file is to run the same command what we run from command line. If we type the series of command in normal file and save this file with .bat extension then this file converted to batch file. Above mentioned extension is only for windows machines for different operating machine batch extensions are different.

So now question is how to run a batch file from java ?

Sample snippet given below :

    public static void main(String[] args) throws IOException {
        try {
            String[] command = { "cmd.exe", "/C", "Start", "runTestNGScript.bat" };
            Process p = Runtime.getRuntime().exec(command);
        } catch (IOException ex) {
      }
    }


Sample batch file given below :
@echo off
echo Set JAVA Path

set PATH=%PATH%;G:\Program Files\Java\jdk1.7.0_79\bin

echo Now PATH is %PATH%


cd %cd%

echo Current Directory %cd%
echo Set Project Path
 
set ProjectPath=%cd%

echo Now project path is : %ProjectPath%


echo Set Class Path

set classpath=%ProjectPath%\bin;%ProjectPath%\lib\*

echo Now project Class path is : %classpath%

echo start compiling
 

javac test\com\automation\test\*.java -cp lib\* -d bin
 

echo Project compiled

echo run test class using TestNG
 

java org.testng.TestNG %ProjectPath%\testng.xml
 

echo Run completed
 

pause

Saturday, May 14, 2016

Custom Cucumber Reporting Using Maven

On previous post we learn how to create custom cucumber report using normal java project.

If we use this report for normal java project we create a custom annotation to generate this report, but if we use maven for this report then it is so easy to create the report and we need very less code.

So how we create this custom cucumber report using maven

Step 1:

 Open eclipse and go to this path File ->New -> Project... ->Maven -> Maven Project.

Click on next after select the Maven Project

Step 2:

 Check the  "Create a simple project (skip archetype selection)" and click on next.
Type the Group Id and Artifact Id under the Artifact section and click finish button.
Group Id means if any organization have multiple project under one group like here we group all cucumber projects under one group.

Artifact Id is the project name.

Step 3:

Our project structure now created in our eclipse work space and it looks like



Step 4 :

We create feature file and put it under src/test/resources.Cucumber runner as well as step file put into src/test/java after creating package. So it looks like


 Step 5 :

Create pom.xml file with all the details and run it using the below command. Here we need to remember that custom report only generated if we use verify or later sequence command from maven default life cycle. So we use install here.

clean install site



Step 6:

 After running this pom.xml report generated under target folder.






Complete Code :

Feature File:

Feature: Calculator
  As a user
  I want to use a calculator
  So that I don't need to calculate myself

  Scenario: Add two numbers
    Given I have a calculator
    When I add 2 and 3
    Then the result should be 4


Step File :

package com.selenium.cucumber.steps;
import org.junit.Assert;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class StepFile {
    int actualSum;

    @Given("^I have a calculator$")
    public void iHaveACalculator() throws Throwable {

    }

    @When("^I add (\\d+) and (\\d+)$")
    public void iAddAnd(int value1, int value2) throws Throwable {
        actualSum = value1 + value2;
    }

    @Then("^the result should be (\\d+)$")
    public void theResultShouldBe(int expectedSum) throws Throwable {
        Assert.assertEquals(expectedSum, actualSum);
    }

}

 

Runner :
package com.selenium.cucumber.runner;

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

@CucumberOptions(plugin = { "html:target/cucumber-html-report", "json:target/cucumber.json" }, features = {
        "src/test/resources/featureFile.feature" }, glue = {
                "com/selenium/cucumber/steps" }, strict = true, dryRun = false, monochrome = true, snippets = SnippetType.CAMELCASE)

@RunWith(Cucumber.class)
public class CucumberRunner {
    public static void generateReport() {

    }
}


pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.selenium.cucumber</groupId>
    <artifactId>CucumberReport</artifactId>
    <version>0.0.1</version>
    <dependencies>
        <!--Dependency For Cucumber Java -->
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.2.4</version>
        </dependency>
        <!-- Dependency For Cucumber JUnit Runner -->
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.4</version>
        </dependency>
        <!-- Dependency For Cucumber Custom Report -->
        <dependency>
            <groupId>net.masterthought</groupId>
            <artifactId>cucumber-reporting</artifactId>
            <version>2.2.0</version>
        </dependency>

    </dependencies>
    <!-- Build Part -->
    <build>
        <plugins>
            <!-- Maven Sure Fire Plug In. It is used to select runner class from any
                folder location as well as not stop to execution whenever any test fail -->

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <includes>
                        <include>com/selenium/cucumber/runner/CucumberRunner.java</include>
                    </includes>
                    <printSummary>true</printSummary>
                    <testFailureIgnore>true</testFailureIgnore>
                </configuration>
            </plugin>
            <!-- This is for Cucumber Custom Report plug in we specify the configuration
                details under configuration tag. -->

            <plugin>
                <groupId>net.masterthought</groupId>
                <artifactId>maven-cucumber-reporting</artifactId>
                <version>2.0.0</version>
                <executions>
                    <execution>
                        <id>execution</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <projectName>CucumberReport</projectName>
                            <outputDirectory>${project.build.directory}/cucumber-html-reports</outputDirectory>
                            <cucumberOutput>${project.build.directory}/cucumber.json</cucumberOutput>
                            <parallelTesting>false</parallelTesting>
                            <buildNumber>1</buildNumber>
                            <checkBuildResult>false</checkBuildResult>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <!-- This is for Maven Sure Fire Report plug in.It is used to create documentation
        and html report for this project -->

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
                <version>2.19.1</version>
                <reportSets>
                    <reportSet>
                        <reports>
                            <report>report-only</report>
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
        </plugins>
    </reporting>
</project>