Você está na página 1de 115

Download Apache POI

Steps to follow:
1) Go to Apache POI services and click on Download on the left side menu.

2) You will always get the latest version here. Click on the link for Apchae POI under Available
Downloads.

3) Click on the ZIP file to start the downloading.


4) Click on the highlighted link at the top of the page.

5) Select the radio button for Save File and click OK. Zip file will be saved on the system with in few
seconds.
6) Right click on the Zip file and select Extract All.

7) Specify the location.


8) Wait for the Extraction to finish.

Adding Apache POI JARS to Project


Library
Steps to follow:
1) Right click the project name, navigate to Build Path and select Configure Build Path.

2) Click on Add External JARS and navigate to the folder where you have kept the Apache POI jar
files.
3) Select the Executable Jar files from all the folders.
Data Driven Framework with Apache POI
Excel
Most commercial automated software tools on the market support some sort of data driven testing,
which allows you to automatically run a test case multiple times with different input and validation
values. As Selenium Webdriver is more an automated testing framework than a ready-to-use tool, you
will have to put in some effort to support data driven testing in your automated tests. I usually prefer
to use Microsoft Excel as the format for storing my parameters. An additional advantage of using Excel
is that you can easily outsource the test data administration to someone other than yourself, someone
who might have better knowledge of the test cases that need to be run and the parameters required
to execute them.

Reading data from the Excel


We need a way to open this Excel sheet and read data from it within our Selenium test script. For this
purpose, I use the Apache POI library, which allows you to read, create and edit Microsoft Office-
documents using Java. The classes and methods we are going to use to read data from Excel sheet
are located in the org.apache.poi.hssf.usermodel package.

How to do it
1) Download JAR files of Apache POI and Add Jars to your project library. You can download it
from here. Thats all about configuration of Apache POI with eclipse. Now you are ready to write your
test.
2) Create a New Package file and name it as testData, by right click on the Project and
select New > Package. Place all of your test data in this folder (package) whether it is a sql file,
excel file or anything.
3) Place a Excel file in the above created package location and save it asTestData.xlsx. Fill the data
in the excel like below image:

4) Add two constant variables (testData package path & Excel file name) in theConstant class.

1 package utility;
2
3 public class Constant {
4
5 public static final String URL = "http://www.store.demoqa.com";
6
7 public static final String Username = "testuser_1";
8
9 public static final String Password = "Test@123";
10
11 public static final String Path_TestData = "D://ToolsQA//OnlineStore//src//testData//"
12
13 public static final String File_TestData = "TestData.xlsx"
14
15 }
5) Create a New Class file, by right click on the utility Package and select New> Class and name
it as ExcelUtils. First we will write basic read/write methods.

1 package utility;
2
3 import java.io.FileInputStream;
4
5 import java.io.FileOutputStream;
6
7 import org.apache.poi.xssf.usermodel.XSSFCell;
8
9 import org.apache.poi.xssf.usermodel.XSSFRow;
10
11 import org.apache.poi.xssf.usermodel.XSSFSheet;
12
13 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
14
15 public class ExcelUtils {
16
17 private static XSSFSheet ExcelWSheet;
18
19 private static XSSFWorkbook ExcelWBook;
20
21 private static XSSFCell Cell;
22
23 private static XSSFRow Row;
24
25 //This method is to set the File path and to open the Excel file, Pass Excel Path and Sheetname as Arguments to this method
26
27 public static void setExcelFile(String Path,String SheetName) throws Exception {
28
29 try {
30
31 // Open the Excel file
32
33 FileInputStream ExcelFile = new FileInputStream(Path);
34
35 // Access the required test data sheet
36
37 ExcelWBook = new XSSFWorkbook(ExcelFile);
38
39 ExcelWSheet = ExcelWBook.getSheet(SheetName);
40
41 } catch (Exception e){
42
43 throw (e);
44
45 }
46
47 }
48
49 //This method is to read the test data from the Excel cell, in this we are passing parameters as Row num and Col num
50
51 public static String getCellData(int RowNum, int ColNum) throws Exception{
52
53 try{
54
55 Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
56
57 String CellData = Cell.getStringCellValue();
58
59 return CellData;
60
61 }catch (Exception e){
62
63 return"";
64
65 }
66
67 }
68
69 //This method is to write in the Excel cell, Row num and Col num are the parameters
70
71 public static void setCellData(String Result, int RowNum, int ColNum) throws Exception {
72
73 try{
74
75 Row = ExcelWSheet.getRow(RowNum);
76
77 Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL);
78
79 if (Cell == null) {
80
81 Cell = Row.createCell(ColNum);
82
83 Cell.setCellValue(Result);
84
85 } else {
86
87 Cell.setCellValue(Result);
88
89 }
90
91 // Constant variables Test Data path and Test Data file name
92
93 FileOutputStream fileOut = new FileOutputStream(Constant.Path_TestData +
94 Constant.File_TestData);
95
96 ExcelWBook.write(fileOut);
97
98 fileOut.flush();
99
100 fileOut.close();
101
102 }catch(Exception e){
103
104 throw (e);
105
106 }
107
108 }
109
}
6) Once we are done with writing Excel functions we can go ahead and modify
the SignIn_Action module to accept the test data from excel file.

1 package appModules;
2
3 import org.openqa.selenium.WebDriver;
4
5 import pageObjects.Home_Page;
6
7 import pageObjects.LogIn_Page;
8
9 import utility.ExcelUtils;
10
11 // Now this method does not need any arguments
12
13 public class SignIn_Action {
14
15 public static void Execute(WebDriver driver) throws Exception{
16
17 //This is to get the values from Excel sheet, passing parameters (Row num & Col num)to getCellData method
18
19 String sUserName = ExcelUtils.getCellData(1, 1);
20
21 String sPassword = ExcelUtils.getCellData(1, 2);
22
23 Home_Page.lnk_MyAccount(driver).click();
24
25 LogIn_Page.txtbx_UserName(driver).sendKeys(sUserName);
26
27 LogIn_Page.txtbx_Password(driver).sendKeys(sPassword);
28
29 LogIn_Page.btn_LogIn(driver).click();
30
31 }
32
33 }
Note: In the later chapters we will see how to parameterise the row column as well, as we also have
to avoid hard coded values in the scripts. This is just to give you an idea to use Excel and we will
move forward step by step towards proper framework.
7) Create a New Class and name it as Apache_POI_TC by right click on the
automationFramework Package and select New > Class. In this we will read the values from the
Excel sheet to use them as the test data and write the test result in the Excel.

1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.firefox.FirefoxDriver;
8
9 import pageObjects.*;
10
11 import utility.Constant;
12
13 // Import Package utility.*
14
15 import utility.ExcelUtils;
16
17 import appModules.SignIn_Action;
18
19 public class Apache_POI_TC {
20
21 private static WebDriver driver = null;
22
23 public static void main(String[] args) throws Exception {
24
25 //This is to open the Excel file. Excel path, file name and the sheet name are parameters to this method
26
27 ExcelUtils.setExcelFile(Constant.Path_TestData + Constant.File_TestData,"Sheet1");
28
29 driver = new FirefoxDriver();
30
31 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
32
33 driver.get(Constant.URL);
34
35 SignIn_Action.Execute(driver);
36
37 System.out.println("Login Successfully, now it is the time to Log Off buddy.");
38
39 Home_Page.lnk_LogOut(driver).click();
40
41 driver.quit();
42
43 //This is to send the PASS value to the Excel sheet in the result column.
44
45 ExcelUtils.setCellData("Pass", 1, 3);
46
47 }
48
49 }
Give it a run, see how beautify your script will execute the code.
8) Once it finished open the Excel file and check for the result.
Your Project explorer window will look like this now.

Do not worry about the red cross signs on your test scripts, it is because we have removed arguments
from SignIn_Action class.
Data Driven framework can be build up by using TestNg Data Provider.

Log4J Logging
During the running of test case user wants some information to be logged in the console. Information
could be any detail depends upon the purpose. Keeping this in mind that we are using Selenium for
testing, we need the information which helps the User to understand the test steps or any failure
during the test case execution. With the help of Log4j it is possible to enable loggings during the
Selenium test case execution for e.g. lets say you have encountered a failure in automation test script
and it has to be reported in the system. The set of information that you have required to report a bug
is :

A complete test steps to replicate the scenario


Issue, Description of the failure or reason for the failed test case
Time stamp for the developers to investigate the issue in detail
Log4j helps us to acheive the above objectives in Selenium Webdriver. When logging is wisely used, it
can prove to be an essential tool.

Logging inside the Methods


Logging inside the testcase is very tedious task and sooner or later you will find it boring and
annoying. Plus everybody has their own way of writing log messages and messages can be less
informative and confusing. So why not make it universal. Writing logs message inside the methods is
much helpful way, with that we can avoid lots of confusions, save lot of time and maintain
consistency.

How to do it
1) Download JAR files of Log4j and Add Jars to your project library. You can download it
from here. Thats all about configuration of Apache POI with eclipse. Now you are ready to write your
test.
2) Create a new XML file log4j.xml and place it under the Project root folder.
3) Paste the following code in the log4j.xml file.

1 <?xml version="1.0" encoding="UTF-8"?>


2
3 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
4
5 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
6
7 <appender name="fileAppender" class="org.apache.log4j.FileAppender">
8
9 <param name="Threshold" value="INFO" />
10
11 <param name="File" value="logfile.log"/>
12
13 <layout class="org.apache.log4j.PatternLayout">
14
15 <param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
16
17 </layout>
18
19 </appender>
20
21 <root>
22
23 <level value="INFO"/>
24
25 <appender-ref ref="fileAppender"/>
26
27 </root>
28
29 </log4j:configuration>
Note: After pasting the code make sure that the code is exactly same, as copying from HTML may
change some symbols () to (?).
Lets take an example of our previous Apache_POI_TC test case and put log messages in every
method and module it interacts with.
4) To achieve that we need to create a static Log class, so that we can access its log method in any of
our project class. Log class will look like this:

1 package utility;
2
3 import org.apache.log4j.Logger;
4
5 public class Log {
6
7 // Initialize Log4j logs
8
9 private static Logger Log = Logger.getLogger(Log.class.getName());//
10
11 // This is to print log for the beginning of the test case, as we usually run so many test cases as a test suite
12
13 public static void startTestCase(String sTestCaseName){
14
15 Log.info("****************************************************************************************");
16
17 Log.info("****************************************************************************************");
18
19 Log.info("$$$$$$$$$$$$$$$$$$$$$ "+sTestCaseName+ " $$$$$$$$$$$$$$$$$$$$$$$$$");
20
21 Log.info("****************************************************************************************");
22
23 Log.info("****************************************************************************************");
24
25 }
26
27 //This is to print log for the ending of the test case
28
29 public static void endTestCase(String sTestCaseName){
30
31 Log.info("XXXXXXXXXXXXXXXXXXXXXXX "+"-E---N---D-"+" XXXXXXXXXXXXXXXXXXXXXX");
32
33 Log.info("X");
34
35 Log.info("X");
36
37 Log.info("X");
38
39 Log.info("X");
40
41 }
42
43 // Need to create these methods, so that they can be called
44
45 public static void info(String message) {
46
47 Log.info(message);
48
49 }
50
51 public static void warn(String message) {
52
53 Log.warn(message);
54
55 }
56
57 public static void error(String message) {
58
59 Log.error(message);
60
61 }
62
63 public static void fatal(String message) {
64
65 Log.fatal(message);
66
67 }
68
69 public static void debug(String message) {
70
71 Log.debug(message);
72
73 }
74
75 }
5) Insert log messages in Home_Page class of pageObject package.

1 package pageObjects;
2
3 import org.openqa.selenium.By;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.WebElement;
8
9 import framework.utility.Log;
10
11 public class Home_Page {
12
13 private static WebElement element = null;
14
15 public static WebElement lnk_MyAccount(WebDriver driver){
16
17 element = driver.findElement(By.id("account"));
18
19 Log.info("My Account link element found");
20
21 return element;
22
23 }
24
25 public static WebElement lnk_LogOut(WebDriver driver){
26
27 element = driver.findElement(By.id("account_logout"));
28
29 Log.info("Log Out link element found");
30
31 return element;
32
33 }
34
35 }
6) Insert log messages in LogIn_Page class of pageObject package.

1 package pageObjects;
2
3 import org.openqa.selenium.*;
4
5 import utility.Log;
6
7 public class LogIn_Page {
8
9 static WebElement element = null;
10
11 public static WebElement txtbx_UserName(WebDriver driver){
12
13 element = driver.findElement(By.id("log"));
14
15 Log.info("Username text box found");
16
17 return element;
18
19 }
20
21 public static WebElement txtbx_Password(WebDriver driver){
22
23 element = driver.findElement(By.id("pwd"));
24
25 Log.info("Password text box found");
26
27 return element;
28
29 }
30
31 public static WebElement btn_LogIn(WebDriver driver){
32
33 element = driver.findElement(By.id("login"));
34
35 Log.info("Submit button found");
36
37 return element;
38
39 }
40
41 }
7) Insert log messages in SignIn_Action class of appModule package.

1 package appModules;
2
3 import org.openqa.selenium.WebDriver;
4
5 import pageObjects.Home_Page;
6
7 import pageObjects.LogIn_Page;
8
9 import utility.ExcelUtils;
10
11 import utility.Log;
12
13 public class SignIn_Action {
14
15 public static void Execute(WebDriver driver) throws Exception{
16
17 String sUserName = ExcelUtils.getCellData(1, 1);
18
19 Log.info("Username picked from Excel is "+ sUserName );
20
21 String sPassword = ExcelUtils.getCellData(1, 2);
22
23 Log.info("Password picked from Excel is "+ sPassword );
24
25 Home_Page.lnk_MyAccount(driver).click();
26
27 Log.info("Click action performed on My Account link");
28
29 LogIn_Page.txtbx_UserName(driver).sendKeys(sUserName);
30
31 Log.info("Username entered in the Username text box");
32
33 LogIn_Page.txtbx_Password(driver).sendKeys(sPassword);
34
35 Log.info("Password entered in the Password text box");
36
37 LogIn_Page.btn_LogIn(driver).click();
38
39 Log.info("Click action performed on Submit button");
40
41 }
42
43 }
8) Now it is the time to insert log message in to your test script but before that create a New Class
and name it as Log4j_Logging_TC by right click on the automationFramework Package and
select New > Class.

1 package automationFramework;
2
3 // Import Package Log4j.*
4
5 import org.apache.log4j.xml.DOMConfigurator;
6
7 import java.util.concurrent.TimeUnit;
8
9 import org.openqa.selenium.*;
10
11 import pageObjects.*;
12
13 import utility.*;
14
15 import appModules.*;
16
17 public class Log4j_Logging_TC {
18
19 private static WebDriver driver = null;
20
21 public static void main(String[] args) throws Exception {
22
23 // Provide Log4j configuration settings
24
25 DOMConfigurator.configure("log4j.xml");
26
27 Log.startTestCase("Selenium_Test_001");
28
29 ExcelUtils.setExcelFile(Constant.Path_TestData + Constant.File_TestData,"Sheet1");
30
31 Log.info(" Excel sheet opened");
32
33 driver = new FirefoxDriver();
34
35 Log.info("New driver instantiated");
36
37 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
38
39 Log.info("Implicit wait applied on the driver for 10 seconds");
40
41 driver.get(Constant.URL);
42
43 Log.info("Web application launched");
44
45 SignIn_Action.Execute(driver);
46
47 System.out.println("Login Successfully, now it is the time to Log Off buddy.");
48
49 Home_Page.lnk_LogOut(driver).click();
50
51 Log.info("Click action is perfomred on Log Out link");
52
53 driver.quit();
54
55 Log.info("Browser closed");
56
57 ExcelUtils.setCellData("Pass", 1, 3);
58
59 Log.endTestCase("Selenium_Test_001");
60
61 }
62
63 }
Once your test is complete, go to your project root folder and open the log file. Your log file will look
like this:

Your Project explorer window will look like this now.


Note: Still you see some logging in the main test script which ideally has to be avoided or minimised.
I have done this so that it can make sense to you. In coming chapters you will see how to avoid
logging in main test script.
Next chapter is all about TestNG framework which is the most important chapter of the Selenium
Automation Frameworks. Before that I request you to visit first Test Case with TestNG.

TestNG Parameters
Everybody knows the importance of Parameterization in testing and in automation testing. It allows
us to automatically run a test case multiple times with different input and validation values. As
Selenium Webdriver is more an automated testing framework than a ready-to-use tool, you will have
to put in some effort to support data driven testing in your automated tests. I usually prefer to use
Microsoft Excel as the format for storing my parameters but so many of my followers have requested
to write an article on TestNG Data Provider.
TestNG again gives us another interesting feature called TestNG Parameters. TestNG lets you pass
parameters directly to your test methods with your testng.xml.
How to do it
Let me take a very simple example of LogIn application, where the username and password is
required to clear the authentication.
1) Create a test on my demo OnlineStore application to perform LogIn which takes the two string
argument as username & password.
2) Provide Username & Password as parameter using TestNG Annotation.

1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.By;
6
7 import org.openqa.selenium.WebDriver;
8
9 import org.openqa.selenium.firefox.FirefoxDriver;
10
11 import org.testng.annotations.Test;
12
13 import org.testng.annotations.Parameters;
14
15 public class TestngParameters {
16
17 private static WebDriver driver;
18
19 @Test
20
21 @Parameters({ "sUsername", "sPassword" })
22
23 public void test(String sUsername, String sPassword) {
24
25 driver = new FirefoxDriver();
26
27 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
28
29 driver.get("http://www.store.demoqa.com");
30
31 driver.findElement(By.xpath(".//*[@id='account']/a")).click();
32
33 driver.findElement(By.id("log")).sendKeys(sUsername);
34
35 driver.findElement(By.id("pwd")).sendKeys(sPassword);
36
37 driver.findElement(By.id("login")).click();
38
39 driver.findElement(By.xpath(".//*[@id='account_logout']/a")).click();
40
41 driver.quit();
42
43 }
44
45 }
3) The parameter would be passed values from testng.xml which we will see in the next step.

1 <suite name="Suite">
2
3 <test name="ToolsQA">
4
5 <parameter name="sUsername" value="testuser_1"/>
6
7 <parameter name="sPassword" value="Test@123"/>
8
9 <classes>
10
11 <class name="automationFramework.TestngParameters" />
12
13 </classes>
14
15 </test>
16
17 </suite>
Now, run the testng.xml, which will run the parameterTest method. TestNG will try to find a
parameter named sUsername & sPassword.

TestNG DataProviders
When you need to pass complex parameters or parameters that need to be created from Java
(complex objects, objects read from a property file or a database, etc), in such cases parameters
can be passed using Dataproviders. A Data Provider is a method annotated with @DataProvider. A
Data Provider returns an array of objects.
Let us check out the same Sign In examples using Dataproviders.
How to do it
1) Define the method credentials() which is defined as a Dataprovider using the annotation. This
method returns array of object array.
2) Add a method test() to your DataProviderTest class. This method takes two strings as input
parameters.
3) Add the annotation @Test(dataProvider = Authentication) to this method. The attribute
dataProvider is mapped to Authentication.
Test will look like this:

1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.By;
6
7 import org.openqa.selenium.WebDriver;
8
9 import org.openqa.selenium.firefox.FirefoxDriver;
10
11 import org.testng.annotations.DataProvider;
12
13 import org.testng.annotations.Test;
14
15 public class DataProviderTest {
16
17 private static WebDriver driver;
18
19 @DataProvider(name = "Authentication")
20
21 public static Object[][] credentials() {
22
23 return new Object[][] { { "testuser_1", "Test@123" }, { "testuser_1", "Test@123" }};
24
25 }
26
27 // Here we are calling the Data Provider object with its Name
28
29 @Test(dataProvider = "Authentication")
30
31 public void test(String sUsername, String sPassword) {
32
33 driver = new FirefoxDriver();
34
35 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
36
37 driver.get("http://www.store.demoqa.com");
38
39 driver.findElement(By.xpath(".//*[@id='account']/a")).click();
40
41 driver.findElement(By.id("log")).sendKeys(sUsername);
42
43 driver.findElement(By.id("pwd")).sendKeys(sPassword);
44
45 driver.findElement(By.id("login")).click();
46
47 driver.findElement(By.xpath(".//*[@id='account_logout']/a")).click();
48
49 driver.quit();
50
51 }
52
53 }
Run the test by right click on the test case script and select Run As > TestNG Test. Give it few
minutes to complete the execution, once it is finished the results will look like this in the TestNg
Result window.

Note: As the test data is provided two times, the above test executed two times completely.

Selenium Automation Framework


Introduction
Mission critical software undergoes rigorous functional tests, especially supported by automated
testing frameworks. Automating these frameworks and maintaining quality software releases are
critical to business performance. Enterprises often face the dilemma of balancing costs and managing
resources to ensure that automation frameworks cover all the business scenarios and the applications
delivered are error free.
By implementing the appropriate automated testing framework, enterprises can significantly increase
the speed and accuracy of the testing process, provide a higher return on investment (ROI) from
software projects and systematically minimize risk.

Why Framework

A framework defines the organizations way of doing things a Single Standard.


Following this standard would result in the project team achieving:

Script-less representation of Automated tests:

The testing framework should offer point-and-click interface for accessing and
interacting with the application components under testas opposed to presenting line after line of
scripting. Testers should be able to visualize each step of the business scenario, view and edit test
cases intuitively. This will shorten the learning curve for testers and help QA teams meet deadlines.

Data Driven tests:

A key benefit of automating functional testing is the ability to test large volumes of
data on the system quickly. But you must be able to manipulate the data sets, perform calculations,
and quickly create hundreds of test iterations and permutations with minimal effort. Test Automation
Frameworks must have capability to integrate with spreadsheets and provide powerful calculation
features.

Concise Reporting:

The ability to run high volume of tests is of little benefit if the results of the tests
are not easy to understand. The framework must automatically generate reports of the test run and
show the results in an easy-to-read format. The reports should provide specifics about where
application failures occurred and what test data was used. Reports must present application screen
shots for every step to highlight any discrepancies and provide detailed explanations of each
checkpoint pass and failure. Reports must also be easily shared across the entire QA and development
teams.

Standard Scripting and Team Consistency:


Scripting standard should be maintained across the framework library creation,
which includes business components, system communications, data check points, loggers, reporters
etc. Project team should follow the defined scripting standards. Published standards across the project
team pre-empt the effort involved in duplicate coding, which prevent individuals from following their
own coding standards.

Encapsulation from Complexities:

Test engineers are encapsulated from the complexities and critical aspects of the
code. Engineers are exposed only to the implemented libraries and tests are executed by just invoking
the libraries.

Implement and Maximize Re-Usability:

Establish the developed libraries across the organization/project team/product


team, i.e. publish the library and provide access rights. Utilities/components shared across the team.
Usage of available libraries. Minimized effort for repeated regression cycle.

Page Object Model | POM


Creating Selenium test cases can result in an unmaintainable project. One of the reasons is that too
many duplicated code is used. Duplicated code could be caused by duplicated functionality and this
will result in duplicated usage of locators. The disadvantage of duplicated code is that the project is
less maintainable. If some locator will change, you have to walk through the whole test code to adjust
locators where necessary. By using the page object model we can make non-brittle test code and
reduce or eliminate duplicate test code. Beside of that it improves the readability and allows us to
create interactive documentation. Last but not least, we can create tests with less keystroke. An
implementation of the page object model can be achieved by separating the abstraction of the test
object and the test scripts.
Note: We will follow the same example which we have used in First Test Case. Lets assume it our
base test case and implement the Page Object Model (POM) in it.

How to do it
1. Create a New Package file and name it as pageObjects, by right click on the Project and
select New > Package. We will be creating different packages for Page Objects, Utilities, Test Data,
Test Cases and Modular actions. It is always recommended to use this structure, as it is easy to
understand, easy to use and easy to maintain.
2. Create a New Class file and refer the name to the actual page from the test object, by right click
on the above created Package and select New > Class. In our case it
is Home Page and LogIn Page.
3. Now create a Static Method for each Element (Object) in the Home Page. Each method will have
an Argument (driver) and a Return value (element).
1 package pageObjects;
2
3 import org.openqa.selenium.By;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.WebElement;
8
9 public class Home_Page {
10
11 private static WebElement element = null;
12
13 public static WebElement lnk_MyAccount(WebDriver driver){
14
15 element = driver.findElement(By.id("account"));
16
17 return element;
18
19 }
20
21 public static WebElement lnk_LogOut(WebDriver driver){
22
23 element = driver.findElement(By.id("account_logout"));
24
25 return element;
26
27 }
28
29 }
Driver is being passed as an Argument so that Selenium is able to locate the element on the
browser (driver).
Element is returned, so that an Action can be performed on it.
Method is declared as Public Static, so that it can be called in any other method
without instantiate the class.
Follow the same rule for creating LogIn Page class.

1 package pageObjects;
2
3 import org.openqa.selenium.*;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.WebElement;
8
9 public class LogIn_Page {
10
11 private static WebElement element = null;
12
13 public static WebElement txtbx_UserName(WebDriver driver){
14
15 element = driver.findElement(By.id("log"));
16
17 return element;
18
19 }
20
21 public static WebElement txtbx_Password(WebDriver driver){
22
23 element = driver.findElement(By.id("pwd"));
24
25 return element;
26
27 }
28
29 public static WebElement btn_LogIn(WebDriver driver){
30
31 element = driver.findElement(By.id("login"));
32
33 return element;
34
35 }
36
37 }
4) Create a New Class and name it as POM_TC by right click on the automationFramework
Package and select New > Class. We will be creating all our test cases under this package.
Now convert your old First Test Case in to the new Page Object Model test case.

1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.firefox.FirefoxDriver;
8
9 // Import package pageObject.*
10
11 import pageObjects.Home_Page;
12
13 import pageObjects.LogIn_Page;
14
15 public class PageObjectModel {
16
17 private static WebDriver driver = null;
18
19 public static void main(String[] args) {
20
21 driver = new FirefoxDriver();
22
23 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
24
25 driver.get("http://www.store.demoqa.com");
26
27 // Use page Object library now
28
29 Home_Page.lnk_MyAccount(driver).click();
30
31 LogIn_Page.txtbx_UserName(driver).sendKeys("testuser_1");
32
33 LogIn_Page.txtbx_Password(driver).sendKeys("Test@123");
34
35 LogIn_Page.btn_LogIn(driver).click();
36
37 System.out.println(" Login Successfully, now it is the time to Log Off buddy.")
38
39 Home_Page.lnk_LogOut(driver).click();
40
41 driver.quit();
42
43 }
44
45 }
You will notice that once you type Home_Page in your test script and the moment you press dot, all
the methods in the Home Page will display. We can expose methods in order to reduce duplicated
code. We are able to call these method multiple times. This will ensure a better maintainable test
code, because we only have to make adjustments and improvements in one particular place.
Your Project explorer window will look like this now.

It is advisable to maintain Page Objects Repository in the same way QTP maintain its Repository.
Please visit Selenium Object Repository section to learn more.

Modular Driven Framework


In most of the web application we have few set of actions which are always executed in the series of
actions. Rather than writing those actions again and again in our test, we can club those actions in to
a method and then calling that method in our test script. Modularity avoids duplicacy of code. In
future if there is any change in the series of action, all you have to do is to make changes in your
main modular method script. No test case will be impacted with the change.

How to do it..
Look for repeated functionality in your application for example the login functionality. We can simple
wrap this functionality in a method and we can give it a sensible name.
1) Create a New Package file and name it as appModule, by right click on the Project and
select New > Package. We will be creating different packages for Page Objects, Utilities, Test Data,
Test Cases and Modular actions. It is always recommended to use this structure, as it is easy to
understand, easy to use and easy to maintain.
2) Create New Class and name it as SignIn_Action by right click on package appModule and
select New > Class. It will add new class SignIn_Action under package appModule.
3) Now create a Public Static Void Method and name it as Execute and club the following steps in
to it:
Click on the My Account link.
Enter Username
Enter Password
Click on the Submit button
This method will not have any Argument (driver) and Return value as it is a void method.

1 package framework.appModule;
2
3 import org.openqa.selenium.WebDriver;
4
5 import framework.pageObject.Home_Page;
6
7 import framework.pageObject.LogIn_Page;
8
9 public class SignIn_Action{
10
11 public static void Execute(WebDriver driver){
12
13 Home_Page.lnk_SignIn(driver).click();
14
15 LogIn_Page.txtbx_UserName(driver).sendKeys("testuser_1");
16
17 LogIn_Page.txtbx_Password(driver).sendKeys("Test@123");
18
19 LogIn_Page.btn_LogIn(driver).click();
20
21 }
22
23 }
Note: Please visit First Test Case & Page Object Model first, in case you are finding it hard to
understand the above used SignIn_Action class.
4) Create a New Class and name it as Module_TC by right click on the automationFramework
Package and select New > Class. We will be creating all our test cases under this package.
Now convert your old POM_TC in to the new Module based test case.
1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.firefox.FirefoxDriver;
8
9 // Import package appModule.*
10
11 import appModules.SignIn_Action;
12
13 import pageObjects.Home_Page;
14
15 public class Module_TC {
16
17 private static WebDriver driver = null;
18
19 public static void main(String[] args) {
20
21 driver = new FirefoxDriver();
22
23 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
24
25 driver.get("http://www.store.demoqa.com");
26
27 // Use your Module SignIn now
28
29 SignIn_Action.Execute(driver);
30
31 System.out.println("Login Successfully, now it is the time to Log Off buddy.");
32
33 Home_Page.lnk_LogOut(driver).click();
34
35 driver.quit();
36
37 }
38
39 }
You will notice that your call to SignIn_Action will automatically execute all the steps mentioned under
it.
Your Project explorer window will look like this now.
Function Parameters
It is always a good practice to pass parameters when calling the method, rather than providing
parameters inside the method. We can pass parameters through methods, just as in normal
programming code. The code below will show us how we can login with parameterized username and
password.

How to do it
1) First lets have a look over our previous example of SignIn_Action class.

1 package framework.appModule;
2
3 import org.openqa.selenium.WebDriver;
4
5 import framework.pageObject.Home_Page;
6
7 import framework.pageObject.LogIn_Page;
8
9 public class SignIn_Action{
10
11 public static void Execute(WebDriver driver){
12
13 Home_Page.lnk_SignIn(driver).click();
14
15 LogIn_Page.txtbx_UserName(driver).sendKeys("testuser_1");
16
17 LogIn_Page.txtbx_Password(driver).sendKeys("Test@123");
18
19 LogIn_Page.btn_LogIn(driver).click();
20
21 }
22
23 }
Note: Please visit First Test Case, Page Object Model & Modularity first, in case you are finding it
hard to understand the above used SignIn_Action class.
2) Modify the above Execute method of class SignIn_Action to accept string Arguments (Username &
Password).

1 package appModules;
2
3 import org.openqa.selenium.WebDriver;
4
5 import pageObjects.Home_Page;
6
7 import pageObjects.LogIn_Page;
8
9 public class SignIn_Action {
10
11 // Pass Arguments (Username and Password) as string
12
13 public static void Execute(WebDriver driver,String sUsername, String sPassword){
14
15 Home_Page.lnk_MyAccount(driver).click();
16
17 // Enter sUsername variable in place of hardcoded value
18
19 LogIn_Page.txtbx_UserName(driver).sendKeys(sUsername);
20
21 // Enter sPassword variable in place of hardcoded value
22
23 LogIn_Page.txtbx_Password(driver).sendKeys(sPassword);
24
25 LogIn_Page.btn_LogIn(driver).click();
26
27 }
28
29 }
3) Create a New Class and name it as Param_TC by right click on the automationFramework
Package and select New > Class. We will be creating all our test cases under this package.
Now convert your old Module_TCin to the new passing parameters based test case.

1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.firefox.FirefoxDriver;
8
9 import appModules.SignIn_Action;
10
11 import pageObjects.Home_Page;
12
13 public class Param_TC {
14
15 private static WebDriver driver = null;
16
17 public static void main(String[] args) {
18
19 driver = new FirefoxDriver();
20
21 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
22
23 driver.get("http://www.store.demoqa.com");
24
25 // Pass the Arguments (Username and Password) to this method
26
27 SignIn_Action.Execute(driver, "testuser_1","Test@123");
28
29 System.out.println("Login Successfully, now it is the time to Log Off buddy.");
30
31 Home_Page.lnk_LogOut(driver).click();
32
33 driver.quit();
34
35 }
36
37 }
You see how easy it is to pass arguments to your methods. It increase you code readability.
Now your Project explorer window will look like this:

Note: But it is still not the best idea to hardcode your input anywhere in your test script, as it will still
impact the bulk of your test scripts if there is any change in user data. I used this example just to give
you an idea to how we use arguments in method.
In the next chapter of Constant Variable we will learn how to avoid hardcode values in our code.
tant Variables
Test data can be of two types, fixed or variable. If it is fixed, we can easily hard code the test data in
to our test scripts. But sometimes the fixed test data is also used in so many scripts and if it gets
changed then it is a huge task to update all the effected test scripts for example the URL of your test
application. It remains same but once you shifted to other environment, you need to change it in all of
your test scripts. We can easily place the URL in Text file or Excel file outside our test scripts but Java
gives us special feature of creating Constants variables which works exactly the same as Environment
and Global variable in QTP.

How to do it
1) Create a New Package file and name it as utility, by right click on the Project and
select New > Package.
2) Create a New Class file, by right click on the above created Package and select New > Class and
name it as Constant.
3) Assign keywords in this class to your fixed data for e.g. Url, Username and Password.

1 package utility;
2
3 public class Constant {
4
5 public static final String URL = "http://www.store.demoqa.com";
6
7 public static final String Username = "testuser_1";
8
9 public static final String Password = "Test@123";
10
11 }
Constants Variables are declared as public static, so that they can be called in any other methods
without instantiate the class.
Constant Variables are declared a final, so that they cannot be changed during the execution.
4) SignIn_Class will remain same.

1 package appModules;
2
3 import org.openqa.selenium.WebDriver;
4
5 import pageObjects.Home_Page;
6
7 import pageObjects.LogIn_Page;
8
9 public class SignIn_Action {
10
11 public static void Execute(WebDriver driver,String sUsername, String sPassword){
12
13 Home_Page.lnk_MyAccount(driver).click();
14
15 LogIn_Page.txtbx_UserName(driver).sendKeys(sUsername);
16
17 LogIn_Page.txtbx_Password(driver).sendKeys(sPassword);
18
19 LogIn_Page.btn_LogIn(driver).click();
20
21 }
22
23 }
Note: Please visit First Test Case, Page Object Model, Modular Driven &Function
Parameters first, in case you are finding it hard to understand the above used SignIn_Action class.
5) Create a New Class and name it as Global_Var_TC by right click on the
automationFramework Package and select New > Class. We will be creating all our test cases
under this package.
Now pass your Constant Variables (URL, Username and Password) as arguments to
your Execute method of SignIn_Action class in your Global_Var_TC test case.

1 package automationFramework;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.openqa.selenium.firefox.FirefoxDriver;
8
9 import pageObjects.Home_Page;
10
11 import appModules.SignIn_Action;
12
13 // Import package utility.*
14
15 import utility.Constant;
16
17 public class Global_Var_TC {
18
19 private static WebDriver driver = null;
20
21 public static void main(String[] args) {
22
23 driver = new FirefoxDriver();
24
25 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
26
27 // Launch the Online Store Website using Constant Variable
28
29 driver.get(Constant.URL);
30
31 // Pass Constant Variables as arguments to Execute method
32
33 SignIn_Action.Execute(driver,Constant.Username,Constant.Password);
34
35 System.out.println("Login Successfully, now it is the time to Log Off buddy.");
36
37 Home_Page.lnk_LogOut(driver).click();
38
39 driver.quit();
40
41 }
42
43 }
You will notice that once you type Constant and the moment you press dot, all the variables in the
Constant class will display. We can expose variables in order to reduce duplicated code. We are able to
call these Constant variables multiple times. This will ensure a better maintainable test code, because
we only have to make adjustments and improvements in one particular place.
Your Project explorer window will look like this now.

When the test data is not fixed or if the same test script can be executed with the large amount of test
data, we use external files for test data. In next chapter of Data Driven Technique Apache
POI you will see how to set large amount of variable test data for the test scripts.
User Defined Functions
User defined functions (UDF) are the functions which are created by users as per their own
requirement. In order to use a UDF, it is necessary to call the appropriate package file at the
beginning of the program. The header file informs the program of the name, type, and number and
type of arguments, of all of the functions contained.

1 import<packageName>
An UDF function is accessed by simply writing the function name, followed by a list of arguments,
which represent the information being passed to the function. The arguments must be enclosed in
parentheses, and separated by commas: they can be constants, variables, or more complex
expressions.
Automation Best Practices: Avoid logics when writing automation test scripts. Every logic is to be
maintained in the function libraries and only be called with their name in the test scripts. Every
arthematic calculation, date calculation, string manipulation etc. should be avoided in the Test scripts
rather put them in to the functions and use them.
Benefits of User Defined Functions
Can be used in a number of places without rewriting the code.
Code can be made less complex and easier to write.
Parameters can be passed to the function.
Simpler to invoke.
For example: It is a three steps process to open a URL. First Instantiate a New driver,
second Apply an Implicit wait on the driver and third Navigate to URL. Browser can be any
browser; it can be Mozilla, IE or any. It makes sense to create a function for opening a browser which
will accept an argument (Browser Type) and it will open that particular browser. This Browser Type
argument will be driven from the Test Data sheet. To achieve this few more functions are required.
1. Function One: openBrowser(int iTestCaseRow), it will return a WebDriver
2. Function Two: getTestCaseName(String sTestCase), it will return refined Test case name
3. Function Three: getRowContains(String sTestCaseName, int colNum), it will return the row
number of the Test case name from the test data sheet.
How to use it
1) Create a new column (Browser) in the Test Data sheet.

Make some entries in the Constant class for the column numbers:

1 package utility;
2
3 public class Constant {
4
5 public static final String URL = "http://www.store.demoqa.com";
6
7 public static final String Path_TestData = "D://ToolsQA//OnlineStore//src//testData//";
8
9 public static final String File_TestData = "TestData.xlsx";
10
11 //Test Data Sheet Columns
12
13 public static final int Col_TestCaseName = 0;
14
15 public static final int Col_UserName =1 ;
16
17 public static final int Col_Password = 2;
18
19 public static final int Col_Browser = 3;
20
21 }

2) Create a New Class by right click on the utility package then select New > Class and name it
as Utils. Now create a Static Method for Initiate Browser in the Utils class. This method will have
an Argument (TestCase Row) and a Return value (WebDriver).
1 public class Utils {
2
3 public static WebDriver driver = null;
4
5 public static WebDriver openBrowser(int iTestCaseRow) throws Exception{
6
7 String sBrowserName;
8
9 try{
10
11 sBrowserName = ExcelUtils.getCellData(iTestCaseRow, Constant.Col_Browser);
12
13 if(sBrowserName.equals("Mozilla")){
14
15 driver = new FirefoxDriver();
16
17 Log.info("New driver instantiated");
18
19 driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
20
21 Log.info("Implicit wait applied on the driver for 10 seconds");
22
23 driver.get(Constant.URL);
24
25 Log.info("Web application launched successfully");
26
27 }
28
29 }catch (Exception e){
30
31 Log.error("Class Utils | Method OpenBrowser | Exception desc : "+e.getMessage());
32
33 }
34
35 return driver;
36
37 }
38
39 }

3) To get the Test Case row from the Test data sheet, it is required to get Test Case name, so
that it can be searched in the Test Data sheet. Write a function in Utils class to get the Test Case
name. Test case name can be easily get by using this.toString(). This function will return the
package name and the class name for e.g. automationFramework.UDF_TC@2550036c. Another
function is required to refine the long test case name in to UDF_TC.

1 public static String getTestCaseName(String sTestCase)throws Exception{


2
3 String value = sTestCase;
4
5 try{
6
7 int posi = value.indexOf("@");
8
9 value = value.substring(0, posi);
10
11 posi = value.lastIndexOf(".");
12
13 value = value.substring(posi + 1);
14
15 return value;
16
17 }catch (Exception e){
18
19 Log.error("Class Utils | Method getTestCaseName | Exception desc : "+e.getMessage());
20
21 throw (e);
22
23 }

4) Once Test Case name is captured, it can be used as an Argument for a function which will return
the Test case row from the Excel sheet.

1 public static int getRowContains(String sTestCaseName, int colNum) throws Exception{


2 int i;
3 try {
4 int rowCount = ExcelWSheet.getLastRowNum();
5 for ( i=0 ; i<rowCount; i++){
6 if (ExcelUtils.getCellData(i,colNum).equalsIgnoreCase(sTestCaseName)){
7 break;
8 }
9 }
10 return i;
11 }catch (Exception e){
12 Log.error("Class ExcelUtil | Method getRowContains | Exception desc : " + e.getMessage());
13 throw(e);
14 }
15 }

5) Create a New Class by right click on the automationFramework package then


select TestNG > Create a TestNG Class and name it as UDF_TC.
Note: Take previous executed test case TestNG_Framework and modify its Before Method only.
The new test script will look like this:

1 package automationFramework;
2
3 import org.apache.log4j.xml.DOMConfigurator;
4
5 import org.openqa.selenium.WebDriver;
6
7 import org.testng.annotations.*;
8
9 import pageObjects.*;
10
11 import utility.*;
12
13 import appModules.*;
14
15 public class UDF_TC {
16
17 public WebDriver driver;
18
19 private String sTestCaseName;
20
21 private int iTestCaseRow;
22
23 @BeforeMethod
24
25 public void beforeMethod() throws Exception {
26
27 DOMConfigurator.configure("log4j.xml");
28
29 sTestCaseName = this.toString();
30
31 sTestCaseName = Utils.getTestCaseName(this.toString());
32
33 Log.startTestCase(sTestCaseName);
34
35 ExcelUtils.setExcelFile(Constant.Path_TestData + Constant.File_TestData,"Sheet1");
36
37 iTestCaseRow = ExcelUtils.getRowContains(sTestCaseName,Constant.Col_TestCaseName);
38
39 driver = Utils.openBrowser(iTestCaseRow);
40
41 }
42
43 @Test
44
45 public void main() throws Exception {
46
47 SignIn_Action.Execute(driver);
48
49 System.out.println("Login Successfully, now it is the time to Log Off buddy.");
50
51 Home_Page.lnk_LogOut(driver).click();
52
53 Log.info("Click action is performed on Log Out link");
54
55 }
56
57 @AfterMethod
58
59 public void afterMethod() {
60
61 driver.quit();
62
63 }
64
65 }
Isnt it easy to call functions rather than writing them again and again and increase code complexity.

Selenium WebDriver Object Repository


Many of us are migrated from QTP to Selenium and trust me when it comes to Object Repository,
QTP is far better than Selenium WebDriver, who in this world do not want the flexibility
of Intellisence of QTP. Isnt great that you just press the dot after typing the browser name and it
gives you all the pages under that parent browser. Then you again press dot after the page name and
it gives you all the elements of that page.
But still Selenium is a Freeware tool and we should be very thankful to the team behind it for their
efforts.
In this tutorial I will explain that how one can have better Object Repository in Selenium like we have
in QTP and how one can take the advantage of Intellisence in Selenium.
Before moving on to this I would suggest you to go through the Page Object Model first.
Object Repository
Think of a scenario where you have a Webpage and it has multiple sections, multiple frames and
hundreds of WebElements. Obviously you do not want that once you type the page name and it will
give you all the elements available on the webpage. If there are few elements, it is fine to have the
same structure but if there are many then it is advisable to divide your page in to different sections for
e.g. header, footer, left navigation, center content and right navigation. Then categories each
WebElement under their parent element.
Think of another scenario where you have a Product listing page and it has many products available
on that page. Each product has its product price, sales price, info, title, image, add to cart button and
rating. What would be the better approach to it, what would you do when you have multiple same
elements on the page like multiple add to cart button, sale price etc. Would you like to name them like
price_1, price_2 and price_3?

What if I give you an approach which gives you the same behavior we have in QTP. Once you type the
page name, it will give you different parent elements only and on selecting parent element, it will give
you linked child elements only.
How to do it
1) Create a New Class by right click on the pageObjects package then select New > Class and
name it as ProductListing_Page.

1 public class ProductListing_Page {


2
3 }
2) Create another public static class inside the above class pageObjects and name it as Product_1.

1 public class ProductListing_Page {


2
3 public static class Product_1{
4
5 }
6
7 }
3) Now create different Static Methods for each child element of Product _1. These methods will
have an Argument (WebDriver) and a Return value (WebElement).

1 package pageObjects;
2
3 import org.openqa.selenium.WebDriver;
4
5 import org.openqa.selenium.WebElement;
6
7 public class ProductListing_Page {
8
9 public static class Product_1{
10
11 public static WebElement txt_Price(WebDriver driver){
12
13 WebElement element = null;
14
15 // Write Code to find element here
16
17 return element;
18
19 }
20
21 public static WebElement txt_SalesPrice(WebDriver driver){
22
23 WebElement element = null;
24
25 // Write Code to find element here
26
27 return element;
28
29 }
30
31 public static WebElement img_Product(WebDriver driver){
32
33 WebElement element = null;
34
35 // Write Code to find element here
36
37 return element;
38
39 }
40
41 public static WebElement txt_Name(WebDriver driver){
42
43 WebElement element = null;
44
45 // Write Code to find element here
46
47 return element;
48
49 }
50
51 public static WebElement txt_Desc(WebDriver driver){
52
53 WebElement element = null;
54
55 // Write Code to find element here
56
57 return element;
58
59 }
60
61 public static WebElement btn_AddToCart( WebDriver driver){
62
63 WebElement element = null;
64
65 // Write Code to find element here
66
67 return element;
68
69 }
70
71 }
72
73 }
You are done with creating Intellisence structure for your Selenium Object Repository. Now lets taste
the benefits of it.
4) Just type ProductListing_Page in your test script and press dot. It will display all the products you
have specified in your
class.
5) Select Product_1 and again press dot, it will now display all the child elements associated with the
parent Product_1.

Now your complete command will look exactly like QTP command.

1 ProductListing_Page.Product_1.btn_AddToCart(driver).click();
Tell me now, isnt it amazing?
One more example of dividing page in to different groups. Look at the screen of a Shopping website.
We can easily divide this heavy loaded Home Page in to three different sections like Header, Center
Content and Footer. Out of which Header and Footer will remain same through out the website and
can be called again and again through Home Page only.
Before jumping on the main topic of Exception Handling in Selenium Automation Framework,
it is better to have basic understanding of Error, Exception, Exception Handling, Try, Catch, Throw and
Throws statement.

What is an Exception
An Exception is an event, which occurs during the execution of a program, that disrupts the normal
flow of the programs instructions or in simple words, any issue which makes your test case stop in
between the execution is an Exception.

Difference between Error and Exception


An Error indicates serious problems that a reasonable application should not try to catch.
An Exception indicates conditions that a reasonable application might want to catch.
Whenever an error occurs while executing a statement, creates an exception object and then the
normal flow of the program halts and it tries to find someone that can handle the raised exception.
The exception object contains a lot of debugging information such as method hierarchy, line
number where the exception occurred, type of exception etc. When the exception occurs in a
method, the process of creating the exception object and handing it over to runtime environment is
called throwing the exception.

What is Exception Handling


Exception handling refers to the anticipation, detection, and resolution of programming application,
and communications errors. It is the block of code that processes the exception object and helps us by
giving us a chance to act on it.

Why Exception Handling is Important


1) Think of a situation where you have got an exception and you want to print some custom message
in your logs, so that it can be understandable by the whole team.
2) There can be some situations where you want to just eat up the exception and want your test to
carry on with rest of the execution.
3) In case you want to perform some series of steps on occurring of an certain exception for e.g. if
you got an exception because a product is out of stock, that product is no longer displayed on the
page and you want you to go with another product available on the page.
4) In case you want to handle some certain kind of exception in Selenium like
ElementNotSelectableException, ElementNotVisibleException, NoSuchElementException etc.
exceptions.

Different Exceptions in Selenium


There is a complete list of Exceptions mentioned on the Selenium Doc which you may or may not
encounter in course of your testing.
Most common Exceptions:
1) NoSuchElementException : FindBy method cant find the element.
2) StaleElementReferenceException : This tells that element is no longer appearing on the DOM page.
3) TimeoutException: This tells that the execution is failed because the command did not complete in
enough time.
4) ElementNotVisibleException: Thrown to indicate that although an element is present on the DOM, it
is not visible, and so is not able to be interacted with
5) ElementNotSelectableException: Thrown to indicate that may be the element is disabled, and so is
not able to select.
You can access the complete list of exception here, but if you are a beginner that I would suggest you
to move forward as of now. It can be over dose.
How to Handle Exception
Try/Catch: A method catches an exception using a combination of the try and catch keywords. Try is
the start of the block and Catch is at the end of try block to handle the exceptions. A try/catch block
is placed around the code that might generate an exception. Code within a try/catch block is referred
to as protected code, and the syntax for using try/catch looks like the following:

1 try
2
3 {
4
5 // Some code
6
7 }catch(Exception e){
8
9 // Code for Handling the exception
10
11 }
Multiple Catch blocks: A try block can be followed by multiple catch blocks. Like I said earlier, that
there are multiple exceptions and you can expect more than one type of exception on a single code
block and if you like to handle each type of exception separately with a separate block of code. The
syntax for multiple catch blocks looks like the following:

1 try
2
3 {
4
5 //Some code
6
7 }catch(ExceptionType1 e1){
8
9 //Code for Handling the Exception 1
10
11 }catch(ExceptionType2 e2){
12
13 //Code for Handling the Exception 2
14
15 }
There is no restriction on the number of the catch blocks, you can use more than two. You may be
wondering that how does it work. It is pretty simple, if an exception occurs in the protected code, the
exception is thrown to the first catch block in the list. If the exception thrown matches the
ExceptionType1, it gets caught there and it executes the code which is under the same exception
block. If not, the exception passes down to the second catch statement and goes on like this.
Note: In case the exception does not match with any exception type and falls through all catches, the
current method stops execution and exception is thrown. That is why it is advisable to include default
exception as well in the end, so in case if the exception falls through, it can be handled by the default
one.
Throw: Sometimes we want to generate exception explicitly in our code, for example in Selenium
Automation Framework most of the time we print self-written logs, once we catch an exception and
then we need to throw that exception back to the system so that the test case can be
terminated. Throw keyword is used to throw exception to the runtime to handle it.
Throws: When we are throwing any exception in a method and not handling it, then we need to
use throws keyword in method signature to let caller program know the exceptions that might be
thrown by the method.

1 // Method Signatur\
2
3 public static void anyFunction() throws Exception{
4
5 try{
6
7 // write your code here
8
9 }catch (Exception e){
10
11 // Do whatever you wish to do here
12
13 // Now throw the exception back to the system
14
15 throw(e);
16
17 }
18
19 }
Multiple Exceptions: We can provide multiple exceptions in the throws clause.

1 public static void anyFunction() throws ExceptionType1, ExceptionType2{


2
3 try {
4
5 //Some code
6
7 }catch(ExceptionType1 e1){
8
9 //Code for Handling the Exception 1
10
11 }catch(ExceptionType2 e2){
12
13 //Code for Handling the Exception 2
14
15 }
Finally: The finally keyword is used to create a block of code that follows a try block. A finally block of
code always executes, whether or not an exception has occurred.

1 try
2
3 {
4
5 //Protected code
6
7 }catch(ExceptionType1 e1)
8
9 {
10
11 //Catch block
12
13 }catch(ExceptionType2 e2)
14
15 {
16
17 //Catch block
18
19 }catch(ExceptionType3 e3)
20
21 {
22
23 //Catch block
24
25 }finally
26
27 {
28
29 //The finally block always executes.
30
31 }

Exception Handling in Selenium


Your Selenium test should be able to fail, but not because of exceptions that are thrown. If your test is
failing from exceptions then quite likely you have no exception handling. By doing this, you dont have
the opportunity to cleanup the WebDriver object at the end of the test.
The tests should be failing under your terms only for example, you should never be getting exceptions
like NullPointerException but if you are getting such as ElementNotFoundException, then also it is
good idea to catch the exception, stop the further execution and end your test in a Logical way.
Example 1: I do not use any Page Object Factory but I use my own Page Object Pattern and I always
print error logs and take screenshot on any exception I encounter. Please look at the code below:

1 public static WebElement btn_ReportCategory(WebDriver driver) throws Exception{


2
3 try{
4
5 WebElement element = driver.findElement(By.linkText("+ Report Categories"));
6
7 }catch (Exception e){
8
9 // Printing logs for my report
10
11 Log.error("Report Category button element is not found.");
12
13 // Taking screenshot for defect reporting
14
15 Utils.captureScreenShot();
16
17 // After doing my work, now i want to stop my test case
18
19 throw(e);
20
21 }
22
23 // This will return the Element in case of no Exception
24
25 return element;
26
27 }
Example 2: TimeoutException using Selenium WebDriver.

1 try{
2
3 myTestDriver.findElement(By.xpath("//*[@id='register']")).click();
4
5 }catch (TimeoutException toe) {
6
7 wait.until( ExpectedConditions.elementToBeClickable(By.xpath("//*[@id='register']")));
8
9 myTestDriver.findElement(By.xpath("//*[@id='register']")).click();
10
11 }catch (Exception e) {
12
13 Log.error("Register element is not found.");
14
15 throw(e);
16
17 }
18
19 }
Example 3: Lets assume that in Selenium WebDriver you want to verify the presence of any element
on the page. You would not be able to get this with element locator because if the element is present,
your locator will work and you will easily be able to print that the element is present but in case your
element is not present on the page, your locator will fail and simply throw the exception. This case
would be easily handled with the self-written function.

1 public static boolean verifyObjectPresent(WebDriver driver) {


2
3 try {
4
5 driver.findElement(By.linkText("+ Report Categories"));
6
7 return true;
8
9 } catch (Exception e) {
10
11 return false;
12
13 }
14
15 }
3Before jumping on the main topic of Exception Handling in Selenium Automation Framework,
it is better to have basic understanding of Error, Exception, Exception Handling, Try, Catch, Throw and
Throws statement.

What is an Exception
An Exception is an event, which occurs during the execution of a program, that disrupts the normal
flow of the programs instructions or in simple words, any issue which makes your test case stop in
between the execution is an Exception.

Difference between Error and Exception


An Error indicates serious problems that a reasonable application should not try to catch.
An Exception indicates conditions that a reasonable application might want to catch.
Whenever an error occurs while executing a statement, creates an exception object and then the
normal flow of the program halts and it tries to find someone that can handle the raised exception.
The exception object contains a lot of debugging information such as method hierarchy, line
number where the exception occurred, type of exception etc. When the exception occurs in a
method, the process of creating the exception object and handing it over to runtime environment is
called throwing the exception.

What is Exception Handling


Exception handling refers to the anticipation, detection, and resolution of programming application,
and communications errors. It is the block of code that processes the exception object and helps us by
giving us a chance to act on it.

Why Exception Handling is Important


1) Think of a situation where you have got an exception and you want to print some custom message
in your logs, so that it can be understandable by the whole team.
2) There can be some situations where you want to just eat up the exception and want your test to
carry on with rest of the execution.
3) In case you want to perform some series of steps on occurring of an certain exception for e.g. if
you got an exception because a product is out of stock, that product is no longer displayed on the
page and you want you to go with another product available on the page.
4) In case you want to handle some certain kind of exception in Selenium like
ElementNotSelectableException, ElementNotVisibleException, NoSuchElementException etc.
exceptions.

Different Exceptions in Selenium


There is a complete list of Exceptions mentioned on the Selenium Doc which you may or may not
encounter in course of your testing.
Most common Exceptions:
1) NoSuchElementException : FindBy method cant find the element.
2) StaleElementReferenceException : This tells that element is no longer appearing on the DOM page.
3) TimeoutException: This tells that the execution is failed because the command did not complete in
enough time.
4) ElementNotVisibleException: Thrown to indicate that although an element is present on the DOM, it
is not visible, and so is not able to be interacted with
5) ElementNotSelectableException: Thrown to indicate that may be the element is disabled, and so is
not able to select.
You can access the complete list of exception here, but if you are a beginner that I would suggest you
to move forward as of now. It can be over dose.
How to Handle Exception
Try/Catch: A method catches an exception using a combination of the try and catch keywords. Try is
the start of the block and Catch is at the end of try block to handle the exceptions. A try/catch block
is placed around the code that might generate an exception. Code within a try/catch block is referred
to as protected code, and the syntax for using try/catch looks like the following:

1 try
2
3 {
4
5 // Some code
6
7 }catch(Exception e){
8
9 // Code for Handling the exception
10
11 }
Multiple Catch blocks: A try block can be followed by multiple catch blocks. Like I said earlier, that
there are multiple exceptions and you can expect more than one type of exception on a single code
block and if you like to handle each type of exception separately with a separate block of code. The
syntax for multiple catch blocks looks like the following:

1 try
2
3 {
4
5 //Some code
6
7 }catch(ExceptionType1 e1){
8
9 //Code for Handling the Exception 1
10
11 }catch(ExceptionType2 e2){
12
13 //Code for Handling the Exception 2
14
15 }
There is no restriction on the number of the catch blocks, you can use more than two. You may be
wondering that how does it work. It is pretty simple, if an exception occurs in the protected code, the
exception is thrown to the first catch block in the list. If the exception thrown matches the
ExceptionType1, it gets caught there and it executes the code which is under the same exception
block. If not, the exception passes down to the second catch statement and goes on like this.
Note: In case the exception does not match with any exception type and falls through all catches, the
current method stops execution and exception is thrown. That is why it is advisable to include default
exception as well in the end, so in case if the exception falls through, it can be handled by the default
one.
Throw: Sometimes we want to generate exception explicitly in our code, for example in Selenium
Automation Framework most of the time we print self-written logs, once we catch an exception and
then we need to throw that exception back to the system so that the test case can be
terminated. Throw keyword is used to throw exception to the runtime to handle it.
Throws: When we are throwing any exception in a method and not handling it, then we need to
use throws keyword in method signature to let caller program know the exceptions that might be
thrown by the method.

1 // Method Signatur\
2
3 public static void anyFunction() throws Exception{
4
5 try{
6
7 // write your code here
8
9 }catch (Exception e){
10
11 // Do whatever you wish to do here
12
13 // Now throw the exception back to the system
14
15 throw(e);
16
17 }
18
19 }
Multiple Exceptions: We can provide multiple exceptions in the throws clause.

1 public static void anyFunction() throws ExceptionType1, ExceptionType2{


2
3 try {
4
5 //Some code
6
7 }catch(ExceptionType1 e1){
8
9 //Code for Handling the Exception 1
10
11 }catch(ExceptionType2 e2){
12
13 //Code for Handling the Exception 2
14
15 }
Finally: The finally keyword is used to create a block of code that follows a try block. A finally block of
code always executes, whether or not an exception has occurred.

1 try
2
3 {
4
5 //Protected code
6
7 }catch(ExceptionType1 e1)
8
9 {
10
11 //Catch block
12
13 }catch(ExceptionType2 e2)
14
15 {
16
17 //Catch block
18
19 }catch(ExceptionType3 e3)
20
21 {
22
23 //Catch block
24
25 }finally
26
27 {
28
29 //The finally block always executes.
30
31 }

Exception Handling in Selenium


Your Selenium test should be able to fail, but not because of exceptions that are thrown. If your test is
failing from exceptions then quite likely you have no exception handling. By doing this, you dont have
the opportunity to cleanup the WebDriver object at the end of the test.
The tests should be failing under your terms only for example, you should never be getting exceptions
like NullPointerException but if you are getting such as ElementNotFoundException, then also it is
good idea to catch the exception, stop the further execution and end your test in a Logical way.
Example 1: I do not use any Page Object Factory but I use my own Page Object Pattern and I always
print error logs and take screenshot on any exception I encounter. Please look at the code below:

1 public static WebElement btn_ReportCategory(WebDriver driver) throws Exception{


2
3 try{
4
5 WebElement element = driver.findElement(By.linkText("+ Report Categories"));
6
7 }catch (Exception e){
8
9 // Printing logs for my report
10
11 Log.error("Report Category button element is not found.");
12
13 // Taking screenshot for defect reporting
14
15 Utils.captureScreenShot();
16
17 // After doing my work, now i want to stop my test case
18
19 throw(e);
20
21 }
22
23 // This will return the Element in case of no Exception
24
25 return element;
26
27 }
Example 2: TimeoutException using Selenium WebDriver.

1 try{
2
3 myTestDriver.findElement(By.xpath("//*[@id='register']")).click();
4
5 }catch (TimeoutException toe) {
6
7 wait.until( ExpectedConditions.elementToBeClickable(By.xpath("//*[@id='register']")));
8
9 myTestDriver.findElement(By.xpath("//*[@id='register']")).click();
10
11 }catch (Exception e) {
12
13 Log.error("Register element is not found.");
14
15 throw(e);
16
17 }
18
19 }
Example 3: Lets assume that in Selenium WebDriver you want to verify the presence of any element
on the page. You would not be able to get this with element locator because if the element is present,
your locator will work and you will easily be able to print that the element is present but in case your
element is not present on the page, your locator will fail and simply throw the exception. This case
would be easily handled with the self-written function.

1 public static boolean verifyObjectPresent(WebDriver driver) {


2
3 try {
4
5 driver.findElement(By.linkText("+ Report Categories"));
6
7 return true;
8
9 } catch (Exception e) {
10
11 return false;
12
13 }
14
15 }
What is Keyword Driven Framework?
Keyword Driven Framework is a type of Functional Automation Testing Framework which is also
known as Table-Driven testing or Action Word based testing. The basic working of the Keyword
Driven Framework is to divide the Test Case in to four different parts. First is called as Test Step,
second is Object of Test Step, third is Action on Test Object and fourth is Data for Test Object.

The above categorization can be done and maintained with the help of Excel spread sheet:
Test Step: It is a very small description of the Test Step or the description of the Action going to
perform on Test Object.
Test Object: It is the name of the Web Page object/element, like Username & Password.
Action: It is the name of the action, which is going to perform on any Object such
as click, open browser, input etc.
Test Data: Data can be any value which is needed by the Object to perform any action, like
Username value for Username field.

The idea behind the Keyword Driven approach in automation is to separate the coding from the test
case & test step. This helps a non technical person to understand the automation very well. With this a
manual tester can write Automation scripts. This does not mean that an automation tester is not
needed but in any Keyword Driven project, a hard core technical coder is must needed for setting up
the framework and to work on regular changes and updates of background automation code. But for
an example an automation team can have two manual tester and a automation coder.
Let just understand this concept with the help of an example of our Demo Online Store Application.
Consider that you have to automate a flow where you would need to do the following things:
1. Open a Browser
2. Navigate to URL
3. Click on My Account button
4. Enter Username
5. Enter Password
6. Click on LogIn button
7. Click on LogOut button
8. Close the Browser

Below is the list of common components that you would required to achieve the task:
1. Excel Sheet: This is the sheet which keeps most of the data for Keyword Driven which is needed
for the test like Test Case, Test Steps, Test Objects and Actions.
2. Object Repository: Property file to store the html elements properties of the web application, this
property file will be linked with the Objects in the test
3. Keyword Function Library: In keyword Driven Framework function file plays an important role,
as it stores the working of the actions, so that each action can be callable from this file
4. Data Sheet: Excel file to store the Data value needed by the object to perform some action on it
5. Execution Engine: Test is the only test script we have in Keyword Framework and it contains all
the code to drive the test from Excel sheet, Function Lib and Properties file.
The below image shows the generic work-flow of Keyword Driven Framework:

From the above figure, you can see that the generic flow of a Keyword Driven Framework is something
like this
Execution Engine starts the test and connect with the bundle of test cases and start executing
one by one
Once Test Case is picked, linked test steps are followed sequentially
Test Steps are further connected with Page Objects, Actions & Test Data
Once Execution Engine gets all the required info to perform a test step, it connects with application
and do the step.

Advantages:
1. Less Technical Expertise: Once Framework is set up, manual testers or non technical testers can
easily write test scripts for automation.
2. Easy To Understand: As it is maintained in Excel sheet and no coding is exposed, the test scripts
are easy to read and understand. Keywords & actions resemble so closely manual test cases, which
become easier to write and maintain.
3. Early Start: You can start building Keyword Driven test cases before the application is delivered,
as Object Repository can be easily set up at the later stage. Using information gathered from
Requirements or other documentation, keyword data tables can be created that mirror
corresponding manual test procedures.
4. Re-usability of component: With implementing modularization in Keyword Driven, Re-usability
can be further increased.
5. Re-usability of code: As there is just one Execution Engine in Keyword Driven Framework, it
encourage extreme code re-usability.
Enough talk about it lets get started.
In this tutorial we will learn how to set up Hybrid Keyword Driven Framework. I called it with the
prefix Hybrid because, Originally it is Just a Keyword Driven Framework but when we implement Data
Driven technique in it, it can be called Hybrid Keyword Framework.

Steps to Set Up Keyword Driven Framework:


STEP 1: Automate an End 2 End flow
STEP 2: Identify & Implement Action Keywords
STEP 3: Set Up Data Engine Excel Sheet
STEP 4: Implement Java Reflection class to create Action Keywords run time
STEP 5: Set Up Java Constant Variables for fixed data
STEP 6: Set Up Object Repository properties file
STEP 7: Set Up Test Suite Execution Engine
STEP 8: Set Up Log4j Logging in Framework
STEP 9: Set Up Exception Handling in Framework
STEP 10: Set Up Test Result Reporting
STEP 11: Set Up Data Driven Technique in Framework
STEP 12: Set Up Framework for Manual Testers

STEP 1: Automate an End 2 End flow


The very first step is to automate an end to end flow of the application. For e.g. If I choose to
automate an E-Commerce application, the end to end flow will be like:
1. LogIn to the application
2. Choose a Product
3. Add the Product to the Cart
4. View the Check Out page
5. Provide Personal details
6. Provide Payment details
7. Confirm the Order and verify the Confirmation page

Prerequisite:
1. Java is installed on your computer, to learn more visit Set Up Java.
2. Eclipse IDE should be installed, to learn more visit Set Up Eclipse.
3. WebDriver client is installed on your machine, to learn more visit Set Up WebDriver Java Client.
4. Eclipse IDE is configured with Selenium WebDriver on your machine, to learn more visit Configure
Eclipse with WebDriver.

Now lets write a simple test case of LogIn & LogOut which we discussed on previous chapter. I could
have taken the complete end to end flow, but it will increase the size of the chapters a lot.

How to do it

1. Create a New Package file and name it as executionEngine, by right click on the Project and
select New > Package. We will be creating different packages for Utilities & Configuration files. It
is always recommended to use this structure, as it is easy to understand, easy to use and easy to
maintain.
2. Create a New Class file and name it as DriverScript, by right click on the above created
Package and select New > Class. As this will be our main script, so do not forget to click the check
box for public static void main(string [ ]args) while creating class.
3. Write the Selenium WebDriver test case for the below mentioned steps:
Step 1 Open a Browser
Step 2 Navigate to URL
Step 3 Click on My Account button
Step 4 Enter Username
Step 5 Enter Password
Step 6 Click on LogIn button
Step 7 Click on LogOut button
Step 8 Close the Browser

1 package executionEngine;
2
3 import java.util.concurrent.TimeUnit;
4 import org.openqa.selenium.*;
5 import org.openqa.selenium.firefox.FirefoxDriver;
6
7 public class DriverScript {
8 private static WebDriver driver = null;
9 public static void main(String[] args) {
10 driver = new FirefoxDriver();
11 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
12 driver.get("http://www.store.demoqa.com");
13
14 driver.findElement(By.xpath(".//*[@id='account']/a")).click();
15 driver.findElement(By.id("log")).sendKeys("testuser_3");
16 driver.findElement(By.id("pwd")).sendKeys("Test@123");
17 driver.findElement(By.id("login")).click();
18 driver.findElement (By.xpath(".//*[@id='account_logout']/a")).click();
19 driver.quit();
20 }
21 }
Try giving it a run. From next chapter we will start setting up the Keyword Driven Framework by
following step by step tutorial.

Once you are done with your basic test, next thing you need to do is to step up Action Keywords for
your test steps and record them in to the Excel sheet. After that a separate class will be created for
Action Keywords, so that they can be easily callable in the test with following the keyword driven
methology.

Identify Action Keywords


1. Create a New Package and name it as dataEngine, by right click on the Project and
select New > Package. We will be creating different packages for Utilities & Configuration files. It
is always recommended to use this structure, as it is easy to understand, easy to use and easy to
maintain.
2. Create an ExcelSheet file and name it as DataEngine, by right click on the above
created Package and select New > File. Note: If in case you do not see any option to create a new
Excel file from Eclipse IDE, you can simply go to the dataEngine package directory locally on your
computer and place a newly created Excel file there andthen refresh your project folder in Eclipse.
3. Open the Excel and rename the Sheet 1 to Test Steps.
4. Create the following columns in the Test Steps sheet:
TestCase ID : Test Case IDs will be store in this columns, such
as LogIn_001, Automation_001 etc.
TestScenario ID : Test Scenario IDs will be stored in this, such as TS_01, TS_02 etc.
Description : This will store small description of the Test Step.
Action_Keyword : This will be the keywords for the Actions.
5. Choose logical names for every action in the test. Action Keywords represents the
required action on the object.
Open the Browser : Action Keyword for this action can be openBrowser or startBrowser or
initiateBrowser
Navigate to Website : Action Keyword for this action can be simple navigate or openUrl
Note: Choose Action Keywords very carefully, as it remains same through out the project.

Your DataEngine sheet will look like this:

Implement Action Keywords


1. Create a New Package and name it as config, by right click on the Project and
select New > Package.
2. Create a New Class file and name it as ActionKeywords, by right click on the above
created Package and select New > File.
3. Now create Static methods for each Action Keyword we have recorded in the Excel.

1 package config;

3 import java.util.concurrent.TimeUnit;

5 import org.openqa.selenium.By;

6 import org.openqa.selenium.WebDriver;

7 import org.openqa.selenium.firefox.FirefoxDriver;
8

9 public class ActionKeywords {

10

11 public static WebDriver driver;

12

13 public static void openBrowser(){

14 driver=new FirefoxDriver();

15 }

16

17 public static void navigate(){

18 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

19 driver.get("http://www.store.demoqa.com");

20 }

21

22 public static void click_MyAccount(){

23 driver.findElement(By.xpath(".//*[@id='account']/a")).click();

24 }

25

26 public static void input_Username(){

27 driver.findElement(By.id("log")).sendKeys("testuser_3");

28 }

29

30 public static void input_Password(){

31 driver.findElement(By.id("pwd")).sendKeys("Test@123");

32 }

33

34 public static void click_Login(){

35 driver.findElement(By.id("login")).click();

36 }

37

38 public static void waitFor() throws Exception{

39 Thread.sleep(5000);
40 }

41

42 public static void click_Logout(){

43 driver.findElement (By.xpath(".//*[@id='account_logout']/a")).click();

44 }

45

46 public static void closeBrowser(){

47 driver.quit();

48 }

49

50 }

Now you project folder will look like this:

To run the driverScript with above code, it is required to change the code of main driver script. Next
chapter is all about setting up the Driver Script class with Data Engine excel.

In last chapter, we created Action Keywords and placed them in to the DataEngine
excel sheet, now we need Apache POI in place to connect with the excel sheet in the
Selenium Test.

Set Up Data Engine Apache POI (Excel)


We need a way to open this Excel sheet and read data from it with in this Selenium test
script. For this purpose, I use the Apache POI library, which allows you
to read, create and edit Microsoft Office-documents using Java. The classes and
methods we are going to use to read data from Excel sheet are located in the
org.apache.poi.hssf.usermodel package.

Reading Data from Excel


1. Download JAR files of Apache POI. You can download Apache POI Jar files
from here. Note: The latest version in Sep14 is poi 3.10.1
2. Once you downloaded the JAR files, then Add Jars files to your project
library. Thats all about configuration of Apache POI with eclipse. Now you are ready
to write code.
3. Create a New Package and name it as utility, by right click on the Project folder
and select New > Package.
4. Create a New Class file, by right click on the utility Package and
select New > Class and name it as ExcelUtils. First we will write basic read
method.

1 package utility;
2
3 import java.io.FileInputStream;
4 import org.apache.poi.xssf.usermodel.XSSFCell;
5 import org.apache.poi.xssf.usermodel.XSSFSheet;
6 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
7 public class ExcelUtils {
8 private static XSSFSheet ExcelWSheet;
9 private static XSSFWorkbook ExcelWBook;
10 private static XSSFCell Cell;
11
12 //This method is to set the File path and to open the Excel file
13 //Pass Excel Path and SheetName as Arguments to this method
14 public static void setExcelFile(String Path,String SheetName) throws Exception {
15 FileInputStream ExcelFile = new FileInputStream(Path);
16 ExcelWBook = new XSSFWorkbook(ExcelFile);
17 ExcelWSheet = ExcelWBook.getSheet(SheetName);
18 }
19
20 //This method is to read the test data from the Excel cell
21 //In this we are passing parameters/arguments as Row Num and Col Num
22 public static String getCellData(int RowNum, int ColNum) throws Exception{
23 Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
24 String CellData = Cell.getStringCellValue();
25 return CellData;
26 }
27
28 }
Now Modify your main DriverScript. With the help of Excel Utility, open the Excel file,
read Action Keywords one by one and on each Action Keyword perform the required
step.

1 package executionEngine;
2
3 import config.ActionKeywords;
4 import utility.ExcelUtils;
5
6 public class DriverScript {
7
8 public static void main(String[] args) throws Exception {
9 // Declaring the path of the Excel file with the name of the Excel file
10 String sPath = "D://Tools QA Projects//trunk//Hybrid Keyword Driven//src//dataEngine//DataEngine.xlsx";
11
12 // Here we are passing the Excel path and SheetName as arguments to connect with Excel file
13 ExcelUtils.setExcelFile(sPath, "Test Steps");
14
15 //Hard coded values are used for Excel row & columns for now
16 //In later chapters we will replace these hard coded values with varibales
17 //This is the loop for reading the values of the column 3 (Action Keyword) row by row
18 for (int iRow=1;iRow<=9;iRow++){
19 //Storing the value of excel cell in sActionKeyword string variable
20 String sActionKeyword = ExcelUtils.getCellData(iRow, 3);
21
22 //Comparing the value of Excel cell with all the project keywords
23 if(sActionKeyword.equals("openBrowser")){
24 //This will execute if the excel cell value is 'openBrowser'
25 //Action Keyword is called here to perform action
26 ActionKeywords.openBrowser();}
27 else if(sActionKeyword.equals("navigate")){
28 ActionKeywords.navigate();}
29 else if(sActionKeyword.equals("click_MyAccount")){
30 ActionKeywords.click_MyAccount();}
31 else if(sActionKeyword.equals("input_Username")){
32 ActionKeywords.input_Username();}
33 else if(sActionKeyword.equals("input_Password")){
34 ActionKeywords.input_Password();}
35 else if(sActionKeyword.equals("click_Login")){
36 ActionKeywords.click_Login();}
37 else if(sActionKeyword.equals("waitFor")){
38 ActionKeywords.waitFor();}
39 else if(sActionKeyword.equals("click_Logout")){
40 ActionKeywords.click_Logout();}
41 else if(sActionKeyword.equals("closeBrowser")){
42 ActionKeywords.closeBrowser();}
43
44 }
45 }
46 }

Here we are done with our initial set up of Keyword Driven Framework.The only idea
behind the Keyword Driven framework is to accept the action keywords from the Excel,
so that all the test cases can be easily created in Excel file. But this Framework is just a
draft version. There are plenty of things can be done on it to make it more robust and
effective. In following chapters we will enhance this draft version.

In Previous Chapter we have seen that to perform any Action, we need to compare the value taken
from Excel sheet with the value of each method in Action Keyword class. Till the time there are just a
few methods, this technique would work fine. But think of a scenario where a new actions is adding
almost daily in framework. It will be tedious task to first add a new method in ActionKeyword class
then add that method in to compare statement of DriverEngine test. Think of the size of the list
of IF/ELSE loop after few releases.

Use of Java Reflection Class


Java gives ability to overcome this problem with the help of Refection Classes. Reflection is a very
useful approach to deal with the Java class at runtime as it can be use to load the Java class, call
its methods or analysis the class at runtime. If in case you are not familiar with Java much, I would
suggest you to simply copy paste the code and start using it. Else it is better to Google Java
Reflection Classes and read about it. Just keep in mind the actual need of it, that we are using it to
create a class at runtime and to analyse the Action Keyword class at runtime.

Let me again tell you the need of it in other words, so that the reason can be understood. As of now in
the framework, whenever there is an addition of any new method in Action Keyword class, it is
required to put that newly created method in the if/else loop of the main Driver Script. Just to avoid
that situation it is required to use Java Reflection class, so that when a new method is added, this
reflection class will load all the methods of Action Keyword class at run time.

Action Keyword Class:

1 package config;

3 import java.util.concurrent.TimeUnit;

5 import org.openqa.selenium.By;

6 import org.openqa.selenium.WebDriver;

7 import org.openqa.selenium.firefox.FirefoxDriver;

9 public class ActionKeywords {

10 public static WebDriver driver;


11 public void openBrowser(){

12 driver=new FirefoxDriver();

13 }

14

15 public static void navigate(){

16 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

17 driver.get("http://www.store.demoqa.com");

18 }

19

20 public static void click_MyAccount(){

21 driver.findElement(By.xpath(".//*[@id='account']/a")).click();

22 }

23

24 public static void input_Username(){

25 driver.findElement(By.id("log")).sendKeys("testuser_3");

26 }

27

28 public static void input_Password(){

29 driver.findElement(By.id("pwd")).sendKeys("Test@123");

30 }

31

32 public static void click_Login(){

33 driver.findElement(By.id("login")).click();

34 }

35

36 public static void waitFor() throws Exception{

37 Thread.sleep(5000);

38 }

39

40 public static void click_Logout(){

41 driver.findElement (By.xpath(".//*[@id='account_logout']/a")).click();

42 }
43

44 public static void closeBrowser(){

45 driver.quit();

46 }

47

48 }

Note: There is no change in the Action Keyword class, it is same as like in last chapter.

Driver Script Class:

1 package executionEngine;

3 import java.lang.reflect.Method;

4 import config.ActionKeywords;

5 import utility.ExcelUtils;

7 public class DriverScript {

8 //This is a class object, declared as 'public static'

9 //So that it can be used outside the scope of main[] method

10 public static ActionKeywords actionKeywords;

11 public static String sActionKeyword;

12 //This is reflection class object, declared as 'public static'

13 //So that it can be used outside the scope of main[] method

14 public static Method method[];

15

16 //Here we are instantiating a new object of class 'ActionKeywords'

17 public DriverScript() throws NoSuchMethodException, SecurityException{

18 actionKeywords = new ActionKeywords();

19 //This will load all the methods of the class 'ActionKeywords' in it.
20 //It will be like array of method, use the break point here and do the watch

21 method = actionKeywords.getClass().getMethods();

22 }

23

24 public static void main(String[] args) throws Exception {

25

26 //Declaring the path of the Excel file with the name of the Excel file

27 String sPath = "D://Tools QA Projects//trunk//Hybrid Keyword Driven//src//dataEngine//DataEngine.xlsx";

28

29 //Here we are passing the Excel path and SheetName to connect with the Excel file

30 //This method was created in the last chapter of 'Set up Data Engine'

31 ExcelUtils.setExcelFile(sPath, "Test Steps");

32

33 //Hard coded values are used for Excel row & columns for now

34 //In later chapters we will use these hard coded value much efficiently

35 //This is the loop for reading the values of the column 3 (Action Keyword) row by row

36 //It means this loop will execute all the steps mentioned for the test case in Test Steps sheet

37 for (int iRow = 1;iRow <= 9;iRow++){

38 //This to get the value of column Action Keyword from the excel

39 sActionKeyword = ExcelUtils.getCellData(iRow, 3);

40 //A new separate method is created with the name 'execute_Actions'

41 //You will find this method below of the this test

42 //So this statement is doing nothing but calling that piece of code to execute

43 execute_Actions();

44 }

45 }

46

47 //This method contains the code to perform some action

48 //As it is completely different set of logic, which revolves around the action only,

49 //It makes sense to keep it separate from the main driver script

50 //This is to execute test step (Action)

51 private static void execute_Actions() throws Exception {


52 //This is a loop which will run for the number of actions in the Action Keyword class

53 //method variable contain all the method and method.length returns the total number of methods

54 for(int i = 0;i < method.length;i++){

55 //This is now comparing the method name with the ActionKeyword value got from excel

56 if(method[i].getName().equals(sActionKeyword)){

57 //In case of match found, it will execute the matched method

58 method[i].invoke(actionKeywords);

59 //Once any method is executed, this break statement will take the flow outside of for loop

60 break;

61 }

62 }

63 }

64 }

The above code is now much more clear and simple. If there is any addition of method in Action
Keyword class, driver script will not have any effect of it. It will automatically consider the newly
created method.

You must have noticed that we are using Action Keywords like click_MyAccount(), which is not at
all a good practice. As there will be thousand of elements in any application and to click those
elements we have to write thousands of click action keywords. So ideally there will be just one click
action which should work on every other element on the test application. To achieve that, it is needed
to separate the action from the object. For e.g. there will be a object called MyAccount and
an action called click() and it would work like this: MyAccount.click()
So our next task is to separate all the objects from the actions. To achieve that we need to create
an Object Repository, which will hold all the objects properties in it and then those properties can be
used in the main driver script. We can easily do this with the help of Property file. Normally, Java
properties file is used to store project configuration data or settings. In this tutorial, we will show you
how to set up and use a properties file. Time for action now.

Step 1: Set Up Object Repository properties file


1. Create a new property file by right clicking on config package and select New > File and name it
as OR.
2. Now take out all the object properties from Action Keywords class and put in OR file.
3. All the objects will be defined like this: Object Name = Object Property, where object property
is element locator.
OR text File:
1 # Home Page Objects

2 btn_MyAccount=.//*[@id='account']/a

3 btn_LogOut=.//*[@id='account_logout']

5 # Login Page Object

6 txtbx_UserName=.//*[@id='log']

7 txtbx_Password=.//*[@id='pwd']

8 btn_LogIn=.//*[@id='login']

Step 2: Modify Data Engine sheet to seperate Page


Objects with Actions
1. Insert an extra row in the dataEngine excel sheet just before the Action Keywords column.
2. Name this new row as Page Object.
3. Add all the objects in the Page Object column.
4. Remove the objects names from the Action Keywords, only actions should be left in the Action
Keywords column.
Excel file now look like this:

Step 3: Modify Action Keyword class to work with


OR properties
1. There were three click methods (click_MyAccount(), click_Login(), click_Logout()) in the previous
chapter, replace all the click methods with just one method and name it as click().
2. Now when we have just one click method, this method should know on which element to
perform click action. For that it is required to pass the element as an argument to this method.
3. This argument will be the Object name taken from the Page Object column in the excel sheet.
4. Modify the action methods, so that it can use the OR properties.
Keyword Action Class:

1 package config;

3 import java.util.concurrent.TimeUnit;

4 import static executionEngine.DriverScript.OR;

6 import org.openqa.selenium.By;

7 import org.openqa.selenium.WebDriver;

8 import org.openqa.selenium.firefox.FirefoxDriver;

10 public class ActionKeywords {

11

12 public static WebDriver driver;

13

14 //All the methods in this class now accept 'Object' name as an argument

15 public static void openBrowser(String object){

16 driver=new FirefoxDriver();

17 }

18

19 public static void navigate(String object){

20 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

21 driver.get(Constants.URL);

22 }

23

24 public static void click(String object){

25 //This is fetching the xpath of the element from the Object Repository property file

26 driver.findElement(By.xpath(OR.getProperty(object))).click();
27 }

28

29 public static void input_UserName(String object){

30 driver.findElement(By.xpath(OR.getProperty(object))).sendKeys(Constants.UserName);

31 }

32

33 public static void input_Password(String object){

34 driver.findElement(By.xpath(OR.getProperty(object))).sendKeys(Constants.Password);

35 }

36

37 public static void waitFor(String object) throws Exception{

38 Thread.sleep(5000);

39 }

40

41 public static void closeBrowser(String object){

42 driver.quit();

43 }

44

45 }

Note: We have still used input_Password() and not detached this object from action. We will take
care of this in next coming chapter of Data Driven.
Note: If you see carefully, object argument is passed in every method, even if it is not required in the
method, such as closeBrowser(). This is the mandatory condition of the reflection class that all the
methods will have same arguments, even if the argument is not used in some methods.

Step 4: Changes in Constants class


1. New entry in Constants class for the new column of Page Objects.
2. Modify the value of the Action Keyword column, as we inserted a new column before the Action
Keword column in dataEngine excel sheet.
Constants Variable Class:

1 package config;
2

3 public class Constants {

5 //List of System Variables

6 public static final String URL = "http://www.store.demoqa.com";

7 public static final String Path_TestData = "D://Tools QA Projects//trunk//Hybrid KeyWord Driven//src//dataEngine//DataEngine.xlsx";

8 public static final String Path_OR = "D://Tools QA Projects//trunk//Hybrid KeyWord Driven//src//config//OR.txt";

9 public static final String File_TestData = "DataEngine.xlsx";

10

11 //List of Data Sheet Column Numbers

12 public static final int Col_TestCaseID = 0;

13 public static final int Col_TestScenarioID =1 ;

14 //This is the new column for 'Page Object'

15 public static final int Col_PageObject =3 ;

16 //This column is shifted from 3 to 4

17 public static final int Col_ActionKeyword =4 ;

18

19 //List of Data Engine Excel sheets

20 public static final String Sheet_TestSteps = "Test Steps";

21

22 //List of Test Data

23 public static final String UserName = "testuser_3";

24 public static final String Password = "Test@123";

25

26 }

Step 5: Load OR properties in the Driver Script


Driver Script:
1 package executionEngine;

3 import java.io.FileInputStream;

4 import java.lang.reflect.Method;

5 import java.util.Properties;

7 import config.ActionKeywords;

8 import config.Constants;

9 import utility.ExcelUtils;

10

11 public class DriverScript {

12

13 public static Properties OR;

14 public static ActionKeywords actionKeywords;

15 public static String sActionKeyword;

16 public static String sPageObject;

17 public static Method method[];

18

19 public DriverScript() throws NoSuchMethodException, SecurityException{

20 actionKeywords = new ActionKeywords();

21 method = actionKeywords.getClass().getMethods();

22 }

23

24 public static void main(String[] args) throws Exception {

25

26 String Path_DataEngine = Constants.Path_TestData;

27 ExcelUtils.setExcelFile(Path_DataEngine, Constants.Sheet_TestSteps);

28

29 //Declaring String variable for storing Object Repository path

30 String Path_OR = Constants.Path_OR;

31 //Creating file system object for Object Repository text/property file

32 FileInputStream fs = new FileInputStream(Path_OR);


33 //Creating an Object of properties

34 OR= new Properties(System.getProperties());

35 //Loading all the properties from Object Repository property file in to OR object

36 OR.load(fs);

37

38

39 for (int iRow=1;iRow<=9;iRow++){

40 sActionKeyword = ExcelUtils.getCellData(iRow, Constants.Col_ActionKeyword);

41 sPageObject = ExcelUtils.getCellData(iRow, Constants.Col_PageObject);

42 execute_Actions();

43 }

44 }

45

46 private static void execute_Actions() throws Exception {

47

48 for(int i=0;i<method.length;i++){

49 if(method[i].getName().equals(sActionKeyword)){

50 //This is to execute the method or invoking the method

51 //Passing 'Page Object' name and 'Action Keyword' as Arguments to this method

52 method[i].invoke(actionKeywords,sPageObject);

53 break;

54 }

55 }

56 }

57 }

Note: Name of the object in the OR file is case sensitive, it has to matched exactly the same way it is
mentioned in the DataEngine sheet.
Project folder would look like this:

In the last chapter of Exception handling we learned how to deal with exceptions in the framework. In
all the methods of Action Keyword class and Excel Utils class, try catch block is set up. So now
the framework is forced to eat all the exceptions and forced to change the value of bresult boolean
variable to false. In this chapter we will learn to handle the situation when the bResult variable is
false.
The whole point of setting the bResult variable to false is to stop the execution of the test case and
mark the test case as failed.

How to do it
Step 1: Create an extra column in the Test Case sheet and name it as Results
Step 2: Create another extra column in Test Steps sheet and name it as Results

Step 3: Create two new Constants variables for the results column of Test Case sheet and
Test Step sheet

1 public static final int Col_Result =3 ;

2 public static final int Col_TestStepResult =5 ;

Step 4: Create two new Constants variables for the Pass results & Fail result

1 public static final String KEYWORD_FAIL = "FAIL";

2 public static final String KEYWORD_PASS = "PASS";


Step 5: Create a new method in the Excel Util class which will set the desired value to
the Data Engine Excel sheet.

1 @SuppressWarnings("static-access")

2 //This method is use to write value in the excel sheet

3 //This method accepts four arguments (Result, Row Number, Column Number & Sheet Name)

4 public static void setCellData(String Result, int RowNum, int ColNum, String SheetName) throws Exception {

5 try{

7 ExcelWSheet = ExcelWBook.getSheet(SheetName);

8 Row = ExcelWSheet.getRow(RowNum);

9 Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL);

10 if (Cell == null) {

11 Cell = Row.createCell(ColNum);

12 Cell.setCellValue(Result);

13 } else {

14 Cell.setCellValue(Result);

15 }

16 // Constant variables Test Data path and Test Data file name

17 FileOutputStream fileOut = new FileOutputStream(Constants.Path_TestData);

18 ExcelWBook.write(fileOut);

19 //fileOut.flush();

20 fileOut.close();

21 ExcelWBook = new XSSFWorkbook(new FileInputStream(Constants.Path_TestData));

22 }catch(Exception e){

23 DriverScript.bResult = false;

24 }

25 }
Step 6: Modify the main Driver Script:

1 package executionEngine;

3 import java.io.FileInputStream;

4 import java.lang.reflect.Method;

5 import java.util.Properties;

6 import org.apache.log4j.xml.DOMConfigurator;

7 import config.ActionKeywords;

8 import config.Constants;

9 import utility.ExcelUtils;

10 import utility.Log;

11

12 public class DriverScript {

13

14 public static Properties OR;

15 public static ActionKeywords actionKeywords;

16 public static String sActionKeyword;

17 public static String sPageObject;

18 public static Method method[];

19 public static int iTestStep;

20 public static int iTestLastStep;

21 public static String sTestCaseID;

22 public static String sRunMode;

23 public static boolean bResult;

24

25 public DriverScript() throws NoSuchMethodException, SecurityException{

26 actionKeywords = new ActionKeywords();

27 method = actionKeywords.getClass().getMethods();
28 }

29

30 //The main script is divided in to three parts now

31 //First is main[] method, execution starts from here

32 public static void main(String[] args) throws Exception {

33 ExcelUtils.setExcelFile(Constants.Path_TestData);

34 DOMConfigurator.configure("log4j.xml");

35 String Path_OR = Constants.Path_OR;

36 FileInputStream fs = new FileInputStream(Path_OR);

37 OR= new Properties(System.getProperties());

38 OR.load(fs);

39

40 DriverScript startEngine = new DriverScript();

41 startEngine.execute_TestCase();

42 }

43

44 //Second method, this is to figure out the test cases execution one by one

45 //And to figure out test step execution one by one

46 private void execute_TestCase() throws Exception {

47 int iTotalTestCases = ExcelUtils.getRowCount(Constants.Sheet_TestCases);

48 for(int iTestcase=1;iTestcase<iTotalTestCases;iTestcase++){

49 //Setting the value of bResult variable to 'true' before starting every test case

50 bResult = true;

51 sTestCaseID = ExcelUtils.getCellData(iTestcase, Constants.Col_TestCaseID,


Constants.Sheet_TestCases);
52
sRunMode = ExcelUtils.getCellData(iTestcase, Constants.Col_RunMode,Constants.Sheet_TestCases);
53
if (sRunMode.equals("Yes")){
54
iTestStep = ExcelUtils.getRowContains(sTestCaseID, Constants.Col_TestCaseID,
55 Constants.Sheet_TestSteps);

56 iTestLastStep = ExcelUtils.getTestStepsCount(Constants.Sheet_TestSteps, sTestCaseID,


iTestStep);
57
Log.startTestCase(sTestCaseID);
58
//Setting the value of bResult variable to 'true' before starting every test step
59
60 bResult=true;

61 for (;iTestStep<iTestLastStep;iTestStep++){

62 sActionKeyword = ExcelUtils.getCellData(iTestStep,
Constants.Col_ActionKeyword,Constants.Sheet_TestSteps);
63
sPageObject = ExcelUtils.getCellData(iTestStep, Constants.Col_PageObject,
64 Constants.Sheet_TestSteps);

65 execute_Actions();

66 //This is the result code, this code will execute after each test step

67 //The execution flow will go in to this only if the value of bResult is 'false'

68 if(bResult==false){

69 //If 'false' then store the test case result as Fail

70
ExcelUtils.setCellData(Constants.KEYWORD_FAIL,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
71
//End the test case in the logs
72
Log.endTestCase(sTestCaseID);
73
//By this break statement, execution flow will not execute any
74 more test step of the failed test case

75 break;

76 }

77

78 }

79 //This will only execute after the last step of the test case, if value is not 'false' at any step

80
if(bResult==true){
81
//Storing the result as Pass in the excel sheet
82

83 ExcelUtils.setCellData(Constants.KEYWORD_PASS,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);

84 Log.endTestCase(sTestCaseID);

85 }

86 }

87 }

88 }

89

90 private static void execute_Actions() throws Exception {

91
92 for(int i=0;i<method.length;i++){

93

94 if(method[i].getName().equals(sActionKeyword)){

95 method[i].invoke(actionKeywords,sPageObject);

96 //This code block will execute after every test step

97 if(bResult==true){

98 //If the executed test step value is true, Pass the test step in Excel sheet

99 ExcelUtils.setCellData(Constants.KEYWORD_PASS, iTestStep,
Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
100
break;
101
}else{
102
//If the executed test step value is false, Fail the test step in Excel sheet
103
ExcelUtils.setCellData(Constants.KEYWORD_FAIL, iTestStep,
104 Constants.Col_TestStepResult, Constants.Sheet_TestSteps);

105 //In case of false, the test execution will not reach to last step of closing browser

106 //So it make sense to close the browser before moving on to next test case

107 ActionKeywords.closeBrowser("");

108 break;

Try giving it a run and see if it works fine on your system. Once you done that try changing the xpath
of any object and see the framework handles the failed test case well or not.

What is Data Driven Testing?


Data-driven testing means using a single test to verify many different test cases by driving
the test with input and expected values from an external data source instead of using the same hard-
coded values each time the test runs.
If you look in to our framework, you will find that till now we have been passing values in the code in
the hard coded form. For e.g. UserName & Password. So far only one user name and password is
being used and that is being declared in the constants class but just think of a scenario when there
will be N number of combinations to test for a log-in functionality. And this is just not limited to
username & password only, even in the open browser method we have been using just one browser.
In real world there will be many more browser to test and to pass the browser to test case is
necessary and that can only be done with the use of Data driven technique.
One more flaw is there in our framework, as there are two different input methods for username and
password which is input_UserName & input_Password. Which is not at all right, as we move along
with writing more test of the application, we will find N number of input fields and we will end up with
hundreds of method of input text field.
This situation can be overcome with the help of data driven technique. Once we start with passing test
data from the external source, we would not need different input text fields method. Only one method
of input would be good enough for us, which will accept the test data.
As we have been driving everything from the Data Engine excel sheet, it is better to drive the set
of test data from it as well.

Step 1: Set up Data Engine excel sheet


1. Create an extra column in the test step sheet and name it as Data Set. Insert this Data set column
before the Results column.
2. Enter browser name, username and password in the Data set column for the relevant rows.
3. Replace the keyword input_Username with just input and do the same for input_Password as
well.
Test Steps sheet:

Step 2: Modify Constants class


1. Create a new constant variable for column Data Set.
2. As we have shifted the result columns, do not forget to increment the number of column for Result
constant variable.

1 public static final int Col_DataSet =5 ;


2 public static final int Col_TestStepResult =6 ;

Step 3: Modify Action Keyword Class


1. Change the method of Action Keyword class to accept data as an argument.
2. As we have followed the concept of reflection class of java, we had to change each and every
method of Action Keyword class to accept data as an argument, even if there is no data to be
supplied for any action such as click() method. Click method just need an object to click on, it does
not need and test data but still we need to change it to follow the rule of reflection, otherwise
reflection wont work at all.
3. Change the working code of the method input, replace the constants variable of username to data.
4. Change the working code of the method open browser.

1 package config;

3 import java.util.concurrent.TimeUnit;

4 import static executionEngine.DriverScript.OR;

5 import org.openqa.selenium.By;

6 import org.openqa.selenium.WebDriver;

7 import org.openqa.selenium.chrome.ChromeDriver;

8 import org.openqa.selenium.firefox.FirefoxDriver;

9 import org.openqa.selenium.ie.InternetExplorerDriver;

10 import executionEngine.DriverScript;

11 import utility.Log;

12

13 public class ActionKeywords {

14

15 public static WebDriver driver;

16 //This block of code will decide which browser type to start

17 public static void openBrowser(String object,String data){

18 Log.info("Opening Browser");

19 try{

20 //If value of the parameter is Mozilla, this will execute


21 if(data.equals("Mozilla")){

22 driver=new FirefoxDriver();

23 Log.info("Mozilla browser started");

24 }

25 else if(data.equals("IE")){

26 //You may need to change the code here to start IE Driver

27 driver=new InternetExplorerDriver();

28 Log.info("IE browser started");

29 }

30 else if(data.equals("Chrome")){

31 driver=new ChromeDriver();

32 Log.info("Chrome browser started");

33 }

34

35 int implicitWaitTime=(10);

36 driver.manage().timeouts().implicitlyWait(implicitWaitTime, TimeUnit.SECONDS);

37 }catch (Exception e){

38 Log.info("Not able to open the Browser --- " + e.getMessage());

39 DriverScript.bResult = false;

40 }

41 }

42

43 public static void navigate(String object, String data){

44 try{

45 Log.info("Navigating to URL");

46 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

47 //Constant Variable is used in place of URL

48 driver.get(Constants.URL);

49 }catch(Exception e){

50 Log.info("Not able to navigate --- " + e.getMessage());

51 DriverScript.bResult = false;

52 }
53 }

54

55 public static void click(String object, String data){

56 try{

57 Log.info("Clicking on Webelement "+ object);

58 driver.findElement(By.xpath(OR.getProperty(object))).click();

59 }catch(Exception e){

60 Log.error("Not able to click --- " + e.getMessage());

61 DriverScript.bResult = false;

62 }

63 }

64 //Now this method accepts two value (Object name & Data)

65 public static void input(String object, String data){

66 try{

67 Log.info("Entering the text in " + object);

68 driver.findElement(By.xpath(OR.getProperty(object))).sendKeys(data);

69 }catch(Exception e){

70 Log.error("Not able to Enter UserName --- " + e.getMessage());

71 DriverScript.bResult = false;

72 }

73 }

74

75 public static void waitFor(String object, String data) throws Exception{

76 try{

77 Log.info("Wait for 5 seconds");

78 Thread.sleep(5000);

79 }catch(Exception e){

80 Log.error("Not able to Wait --- " + e.getMessage());

81 DriverScript.bResult = false;

82 }

83 }

84
85 public static void closeBrowser(String object, String data){

86 try{

87 Log.info("Closing the browser");

88 driver.quit();

89 }catch(Exception e){

90 Log.error("Not able to Close the Browser --- " + e.getMessage());

91 DriverScript.bResult = false;

92 }

93 }

94

95 }

Step 4: Modify Driver Engine script


1. Create new variable for Test Data public static String sData;
2. Add a statement to assign value to data variable from the Data Set column of sheet Test Step
3. In execute_Action() block, pass sData variable to invoke method.

1 package executionEngine;

3 import java.io.FileInputStream;

4 import java.lang.reflect.Method;

5 import java.util.Properties;

6 import org.apache.log4j.xml.DOMConfigurator;

7 import config.ActionKeywords;

8 import config.Constants;

9 import utility.ExcelUtils;

10 import utility.Log;

11

12 public class DriverScript {

13
14 public static Properties OR;

15 public static ActionKeywords actionKeywords;

16 public static String sActionKeyword;

17 public static String sPageObject;

18 public static Method method[];

19 public static int iTestStep;

20 public static int iTestLastStep;

21 public static String sTestCaseID;

22 public static String sRunMode;

23 public static String sData;

24 public static boolean bResult;

25

26 public DriverScript() throws NoSuchMethodException, SecurityException{

27 actionKeywords = new ActionKeywords();

28 method = actionKeywords.getClass().getMethods();

29 }

30

31 public static void main(String[] args) throws Exception {

32 ExcelUtils.setExcelFile(Constants.Path_TestData);

33 DOMConfigurator.configure("log4j.xml");

34 String Path_OR = Constants.Path_OR;

35 FileInputStream fs = new FileInputStream(Path_OR);

36 OR= new Properties(System.getProperties());

37 OR.load(fs);

38

39 DriverScript startEngine = new DriverScript();

40 startEngine.execute_TestCase();

41 }

42

43 private void execute_TestCase() throws Exception {

44 int iTotalTestCases = ExcelUtils.getRowCount(Constants.Sheet_TestCases);

45 for(int iTestcase=1;iTestcase<iTotalTestCases;iTestcase++){
46 bResult = true

47 sTestCaseID = ExcelUtils.getCellData(iTestcase, Constants.Col_TestCaseID,


Constants.Sheet_TestCases);
48
sRunMode = ExcelUtils.getCellData(iTestcase, Constants.Col_RunMode,Constants.Sheet_TestCases);
49
if (sRunMode.equals("Yes")){
50
iTestStep = ExcelUtils.getRowContains(sTestCaseID, Constants.Col_TestCaseID,
51 Constants.Sheet_TestSteps);

52 iTestLastStep = ExcelUtils.getTestStepsCount(Constants.Sheet_TestSteps, sTestCaseID,


iTestStep);
53
Log.startTestCase(sTestCaseID);
54
bResult=true;
55
for (;iTestStep<iTestLastStep;iTestStep++){
56
sActionKeyword = ExcelUtils.getCellData(iTestStep,
57 Constants.Col_ActionKeyword,Constants.Sheet_TestSteps);

58 sPageObject = ExcelUtils.getCellData(iTestStep, Constants.Col_PageObject,


Constants.Sheet_TestSteps);
59
//Now we will use the data value and pass it to the methods
60
sData = ExcelUtils.getCellData(iTestStep, Constants.Col_DataSet,
61 Constants.Sheet_TestSteps);

62 execute_Actions();

63 if(bResult==false){

64
ExcelUtils.setCellData(Constants.KEYWORD_FAIL,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
65
Log.endTestCase(sTestCaseID);
66
break;
67
}
68
}
69
if(bResult==true){
70

71 ExcelUtils.setCellData(Constants.KEYWORD_PASS,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);

72 Log.endTestCase(sTestCaseID);

73 }

74

75 }

76

77 }
78 }

79

80 private static void execute_Actions() throws Exception {

81

82 for(int i=0;i<method.length;i++){

83

84 if(method[i].getName().equals(sActionKeyword)){

85 //This code will pass three parameters to every invoke method

86 method[i].invoke(actionKeywords,sPageObject, sData);

87 if(bResult==true){

88 ExcelUtils.setCellData(Constants.KEYWORD_PASS, iTestStep,
Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
89
break;
90
}else{
91
ExcelUtils.setCellData(Constants.KEYWORD_FAIL, iTestStep,
92 Constants.Col_TestStepResult, Constants.Sheet_TestSteps);

93 ActionKeywords.closeBrowser("","");

94 break;

95 }

Note: For any explanation on un-commented code, please refer previous chapters.
You can see now the whole Keyword Driven Framework is set for use. Now it is up to you to
implement other enhancements in this framework like you can implement HTML reporting in it or you
can even implement some sort of automatic email reply on any test fail or an automatic email sent to
the project stakeholders with test execution results or any thing.
But for me the next chapter is dam so important, so do not wait just jump on it.
The overall idea behind the Keyword Driven Framework is to utilize manual testers to write
automation scripts. Given the fact that keywords are so closely resemble a manual test procedure, it
becomes simpler to trace actions in automated tests to actions in manual tests. Working with
keywords data tables for everyday application automation is a lot less technical than working with
code statements. Therefore individuals that are not as technical can be brought onto the team to help
in creating automated tests.
But in order to effectively implement a Keyword framework, reliance on intuition must be reduced,
while reliance on standards must be increased. While some standards are automatically imposed, with
this type of framework, many standards are not, so theres an ongoing effort to ensure resources are
aware of standards, understand them, and are able to effectively implement them.
So the best practice in Keyword Driven framework is to impose the standards automatically, so that
the gap of discrepancy can be reduced. Let me take an example and explain it to you. There is a page
object called txtbx_UserName which represent the Username text box in the application. To
effectively use it in the keyword driven framework, we write the same name in the data engine sheet.
When execution engine reads txtbx_UserName, it knows which object to point from the Object
Repository property file. But this txtbx_UserName is case sensitive, any spelling error in this like
txtbox_UserName would result in an exception.
One of the drawback of the Keyword framework is that it is developed by different set of people who
are more technical and it is used by different set of people who are not very technical, so there is
always a gap. To finish the gap, it is better to impose standards. Means if we can force data engine
sheet in a way, so that the user would not be able to enter any invalid object, which result in to
exceptions.
One more example will explain the situation logically. As we know that there are many continue
buttons on any e-commerce application. Actually almost on every page of an e-commerce application
you would find a continue button. Now as a user of keyword framework, it is difficult to identify the
right continue button he/she would require to click. And it is not the best practice to name continue
button like continue_1 & continue_2, even in this case it would be confusing because the user has
not developed the framework.
This chapter will allow you to avoid any such situations where a user can make mistakes unknowingly.

Step 1: Set up Page Object Model for Keyword


Framework
1) Create an extra sheet in the same data engine excel sheet and name is as Settings.
2) Name the first column as Page Name and mention all the pages of the application under it.

3) Now create new columns for the objects of each Page in the application.
4) Mention all the page objects under the respective page name columns.

5) Create a new column and name it as Action Keywords and mention all the action
keywords under it.
6) Select the range of Page Name column and name the range as Page_Name.

7) Select the range of Home Page objects and name the range as Home_Page.
8) Do the above steps for LogIn Page objects & Action Keywords also.

Step 2: Set up Excel Trick for Application Pages


1) Create a new column in Test Steps sheet before the Page Object column and name it as Page
Name.

2) Select the range of the column Page Name, go to Data tab and then click on Data Validation
drop down and select DataValidation.
3) Select List from the Allow drop down and enter =Page_Name in the Source text box.
Now if you see that when you click on any row of column Page Name, you would get a drop down list
populating all the page name available in the application. This will ensure that the user would not be
able to make any choice which can not be handled with the framework.

4) Do the same for Action Keywords as well and it will display all the actionsavailable to use.

Step 3: Set up Excel trick for Page Objects


1) Select the range of the column Page Object, go to Data tab and then click on Data Validation
drop down and select Data Validation.
2) Select List from the Allow drop down and enter =INDIRECT(D2) in the Source text box.

Click Yes and move forward.


Now if you see that when you click on any row of column Page Objects, you would get a drop down
list populating all the page objects available in the particular page. This will ensure that the user would
not be able to make any choice which can not be handled with the framework.User is now bound to
choose the right object.

Note: If in case you face any issue in setting up this data trick, you follow this link:
http://www.contextures.com/xlDataVal02.html

I hope that you have enjoyed the journey of Step by step tutorial of setting up Keyword Driven
Framework with Selenium WebDriver so far and you have understood all the topics well. Lets revise
what we have covered and do a Practice Exercise on it.

What we have covered in the previous chapters:


1. Automate an End 2 End flow
2. Identify & Implement Action Keywords
3. Set Up Data Engine Excel Sheet
4. Implement Java Reflection class to create Action Keywords run time
5. Set Up Java Constant Variables for fixed data
6. Set Up Object Repository properties file
7. Set Up Test Suite Execution Engine
8. Set Up Log4j Logging in Framework
9. Set Up Exception Handling in Framework
10. Set Up Test Result Reporting
11. Set Up Data Driven Technique in Framework
12. Set Up Framework for Manual Testers
It is almost the end of setting up the framework. We have already covered everything and what is
remaining is expanding the test to cover End to End scenarios. Still there can be many enhancement
pending on this framework such as screenshots, html reporting, emailing status or many more.

Practice Exercise
Before jumping to the next level I would like to do an exercise on what we have learned so far on
the Demo Application. What we have covered so far is the Login functionality only. I would like you to
automate an end to end flow covering below steps:
1. Login to the demo application Online Store
2. Selecting a product category from Top Menu
3. Selecting a product and adding it to the cart
4. Go to payment details page and complete the order
5. Verify details from final Confirmation page

Once you done with the above exercise, please send me your code so that I can share it
with wider audience with your name.
Project Download
Please download the code from here Selenium Automation Keyword Driven Framework
Or please read the code below.

Package: executionEngine
Class: DriverScript

1 package executionEngine;

3 import java.io.FileInputStream;

4 import java.lang.reflect.Method;

5 import java.util.Properties;

7 import org.apache.log4j.xml.DOMConfigurator;

9 import config.ActionKeywords;

10 import config.Constants;

11 import utility.ExcelUtils;
12 import utility.Log;

13

14 public class DriverScript {

15

16 public static Properties OR;

17 public static ActionKeywords actionKeywords;

18 public static String sActionKeyword;

19 public static String sPageObject;

20 public static Method method[];

21

22 public static int iTestStep;

23 public static int iTestLastStep;

24 public static String sTestCaseID;

25 public static String sRunMode;

26 public static String sData;

27 public static boolean bResult;

28

29 public DriverScript() throws NoSuchMethodException, SecurityException{

30 actionKeywords = new ActionKeywords();

31 method = actionKeywords.getClass().getMethods();

32 }

33

34 public static void main(String[] args) throws Exception {

35 ExcelUtils.setExcelFile(Constants.Path_TestData);

36 DOMConfigurator.configure("log4j.xml");

37 String Path_OR = Constants.Path_OR;

38 FileInputStream fs = new FileInputStream(Path_OR);

39 OR= new Properties(System.getProperties());

40 OR.load(fs);

41

42 DriverScript startEngine = new DriverScript();

43 startEngine.execute_TestCase();
44

45 }

46

47 private void execute_TestCase() throws Exception {

48 int iTotalTestCases = ExcelUtils.getRowCount(Constants.Sheet_TestCases);

49 for(int iTestcase=1;iTestcase<iTotalTestCases;iTestcase++){

50 bResult = true;

51 sTestCaseID = ExcelUtils.getCellData(iTestcase, Constants.Col_TestCaseID,


Constants.Sheet_TestCases);
52
sRunMode = ExcelUtils.getCellData(iTestcase, Constants.Col_RunMode,Constants.Sheet_TestCases);
53
if (sRunMode.equals("Yes")){
54
Log.startTestCase(sTestCaseID);
55
iTestStep = ExcelUtils.getRowContains(sTestCaseID, Constants.Col_TestCaseID,
56 Constants.Sheet_TestSteps);

57 iTestLastStep = ExcelUtils.getTestStepsCount(Constants.Sheet_TestSteps, sTestCaseID,


iTestStep);
58
bResult=true;
59
for (;iTestStep<iTestLastStep;iTestStep++){
60
sActionKeyword = ExcelUtils.getCellData(iTestStep,
61 Constants.Col_ActionKeyword,Constants.Sheet_TestSteps);

62 sPageObject = ExcelUtils.getCellData(iTestStep, Constants.Col_PageObject,


Constants.Sheet_TestSteps);
63
sData = ExcelUtils.getCellData(iTestStep, Constants.Col_DataSet,
64 Constants.Sheet_TestSteps);

65 execute_Actions();

66 if(bResult==false){

67
ExcelUtils.setCellData(Constants.KEYWORD_FAIL,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
68
Log.endTestCase(sTestCaseID);
69
break;
70
}
71

72 }

73 if(bResult==true){

74
ExcelUtils.setCellData(Constants.KEYWORD_PASS,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
75
76 Log.endTestCase(sTestCaseID);

77 }

78 }

79 }

80 }

81

82 private static void execute_Actions() throws Exception {

83

84 for(int i=0;i<method.length;i++){

85

86 if(method[i].getName().equals(sActionKeyword)){

87 method[i].invoke(actionKeywords,sPageObject, sData);

88 if(bResult==true){

89 ExcelUtils.setCellData(Constants.KEYWORD_PASS, iTestStep,
Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
90
break;
91
}else{
92
ExcelUtils.setCellData(Constants.KEYWORD_FAIL, iTestStep,
93 Constants.Col_TestStepResult, Constants.Sheet_TestSteps);

94 ActionKeywords.closeBrowser("","");

95 break;

Package: config
Class: Action Keywords

1
package config;
2

3
import java.util.concurrent.TimeUnit;
4

5
import static executionEngine.DriverScript.OR;
6

7
import org.openqa.selenium.By;
8
import org.openqa.selenium.WebDriver;
9
import org.openqa.selenium.chrome.ChromeDriver;
10
import org.openqa.selenium.firefox.FirefoxDriver;
11
import org.openqa.selenium.ie.InternetExplorerDriver;
12

13
import executionEngine.DriverScript;
14
import utility.Log;
15

16
public class ActionKeywords {
17

18
public static WebDriver driver;
19

20
public static void openBrowser(String object,String data){
21
Log.info("Opening Browser");
22
try{
23
if(data.equals("Mozilla")){
24
driver=new FirefoxDriver();
25
Log.info("Mozilla browser started");
26
}
27
28 else if(data.equals("IE")){

29 //Dummy Code, Implement you own code

30 driver=new InternetExplorerDriver();

31 Log.info("IE browser started");

32 }

33 else if(data.equals("Chrome")){

34 //Dummy Code, Implement you own code

35 driver=new ChromeDriver();

36 Log.info("Chrome browser started");

37 }

38

39 int implicitWaitTime=(10);

40 driver.manage().timeouts().implicitlyWait(implicitWaitTime, TimeUnit.SECONDS);

41 }catch (Exception e){

42 Log.info("Not able to open the Browser --- " + e.getMessage());

43 DriverScript.bResult = false;

44 }

45 }

46

47 public static void navigate(String object, String data){

48 try{

49 Log.info("Navigating to URL");

50 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

51 driver.get(Constants.URL);

52 }catch(Exception e){

53 Log.info("Not able to navigate --- " + e.getMessage());

54 DriverScript.bResult = false;

55 }

56 }

57

58 public static void click(String object, String data){

59 try{
60 Log.info("Clicking on Webelement "+ object);

61 driver.findElement(By.xpath(OR.getProperty(object))).click();

62 }catch(Exception e){

63 Log.error("Not able to click --- " + e.getMessage());

64 DriverScript.bResult = false;

65 }

66 }

67

68 public static void input(String object, String data){

69 try{

70 Log.info("Entering the text in " + object);

71 driver.findElement(By.xpath(OR.getProperty(object))).sendKeys(data);

72 }catch(Exception e){

73 Log.error("Not able to Enter UserName --- " + e.getMessage());

74 DriverScript.bResult = false;

75 }

76 }

77

78 public static void waitFor(String object, String data) throws Exception{

79 try{

80 Log.info("Wait for 5 seconds");

81 Thread.sleep(5000);

82 }catch(Exception e){

83 Log.error("Not able to Wait --- " + e.getMessage());

84 DriverScript.bResult = false;

85 }

86 }

87

88 public static void closeBrowser(String object, String data){

89 try{

90 Log.info("Closing the browser");

91 driver.quit();
92 }catch(Exception e){

93 Log.error("Not able to Close the Browser --- " + e.getMessage());

94 DriverScript.bResult = false;

95 }

96 }

97

Class: Constants

1 package config;

3 public class Constants {

5 //System Variables

6 public static final String URL = "http://www.store.demoqa.com";

7 public static final String Path_TestData = "D://Tools QA Projects//trunk//Hybrid KeyWord Driven//src//dataEngine//DataEngine.xlsx";

8 public static final String Path_OR = "D://Tools QA Projects//trunk//Hybrid KeyWord Driven//src//config//OR.txt";

9 public static final String File_TestData = "DataEngine.xlsx";

10 public static final String KEYWORD_FAIL = "FAIL";

11 public static final String KEYWORD_PASS = "PASS";

12

13 //Data Sheet Column Numbers

14 public static final int Col_TestCaseID = 0;

15 public static final int Col_TestScenarioID =1 ;

16 public static final int Col_PageObject =4 ;

17 public static final int Col_ActionKeyword =5 ;

18 public static final int Col_RunMode =2 ;

19 public static final int Col_Result =3 ;


20 public static final int Col_DataSet =6 ;

21 public static final int Col_TestStepResult =7 ;

22

23 // Data Engine Excel sheets

24 public static final String Sheet_TestSteps = "Test Steps";

25 public static final String Sheet_TestCases = "Test Cases";

26

27 }

Properties: Object Repository

1 # Home Page Objects

2 btn_MyAccount=.//*[@id='account']/a

3 btn_LogOut=.//*[@id='account_logout']/a

5 # Login Page Object

6 txtbx_UserName=.//*[@id='log']

7 txtbx_Password=.//*[@id='pwd']

8 btn_LogIn=.//*[@id='login']

Package: dataEngine
Sheet: Test Case
Sheet: Test Steps

Sheet: Test Data

Sheet: Settings

Package: Utility
Class: ExcelUtils

1 package utility;

3 import java.io.FileInputStream;

4 import java.io.FileOutputStream;

6 import org.apache.poi.xssf.usermodel.XSSFSheet;

7 import org.apache.poi.xssf.usermodel.XSSFWorkbook;

8 import org.apache.poi.xssf.usermodel.XSSFRow;

10 import config.Constants;

11 import executionEngine.DriverScript;

12 public class ExcelUtils {

13 private static XSSFSheet ExcelWSheet;

14 private static XSSFWorkbook ExcelWBook;

15 private static org.apache.poi.ss.usermodel.Cell Cell;

16 private static XSSFRow Row;

17 //private static XSSFRow Row;

18

19 public static void setExcelFile(String Path) throws Exception {

20 try {

21 FileInputStream ExcelFile = new FileInputStream(Path);

22 ExcelWBook = new XSSFWorkbook(ExcelFile);

23 } catch (Exception e){

24 Log.error("Class Utils | Method setExcelFile | Exception desc : "+e.getMessage());

25 DriverScript.bResult = false;

26 }

27 }
28

29 public static String getCellData(int RowNum, int ColNum, String SheetName ) throws Exception{

30 try{

31 ExcelWSheet = ExcelWBook.getSheet(SheetName);

32 Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);

33 String CellData = Cell.getStringCellValue();

34 return CellData;

35 }catch (Exception e){

36 Log.error("Class Utils | Method getCellData | Exception desc : "+e.getMessage());

37 DriverScript.bResult = false;

38 return"";

39 }

40 }

41

42 public static int getRowCount(String SheetName){

43 int iNumber=0;

44 try {

45 ExcelWSheet = ExcelWBook.getSheet(SheetName);

46 iNumber=ExcelWSheet.getLastRowNum()+1;

47 } catch (Exception e){

48 Log.error("Class Utils | Method getRowCount | Exception desc : "+e.getMessage());

49 DriverScript.bResult = false;

50 }

51 return iNumber;

52 }

53

54 public static int getRowContains(String sTestCaseName, int colNum,String SheetName) throws Exception{

55 int iRowNum=0;

56 try {

57 //ExcelWSheet = ExcelWBook.getSheet(SheetName);

58 int rowCount = ExcelUtils.getRowCount(SheetName);

59 for (; iRowNum<rowCount; iRowNum++){


60 if (ExcelUtils.getCellData(iRowNum,colNum,SheetName).equalsIgnoreCase(sTestCaseName)){

61 break;

62 }

63 }

64 } catch (Exception e){

65 Log.error("Class Utils | Method getRowContains | Exception desc : "+e.getMessage());

66 DriverScript.bResult = false;

67 }

68 return iRowNum;

69 }

70

71 public static int getTestStepsCount(String SheetName, String sTestCaseID, int iTestCaseStart) throws Exception{

72 try {

73 for(int i=iTestCaseStart;i<=ExcelUtils.getRowCount(SheetName);i++){

74 if(!sTestCaseID.equals(ExcelUtils.getCellData(i, Constants.Col_TestCaseID, SheetName))){

75 int number = i;

76 return number;

77 }

78 }

79 ExcelWSheet = ExcelWBook.getSheet(SheetName);

80 int number=ExcelWSheet.getLastRowNum()+1;

81 return number;

82 } catch (Exception e){

83 Log.error("Class Utils | Method getRowContains | Exception desc : "+e.getMessage());

84 DriverScript.bResult = false;

85 return 0;

86 }

87 }

88

89 @SuppressWarnings("static-access")

90 public static void setCellData(String Result, int RowNum, int ColNum, String SheetName) throws Exception {

91 try{
92

93 ExcelWSheet = ExcelWBook.getSheet(SheetName);

94 Row = ExcelWSheet.getRow(RowNum);

95 Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL);

96 if (Cell == null) {

97 Cell = Row.createCell(ColNum);

98 Cell.setCellValue(Result);

99 } else {

100 Cell.setCellValue(Result);

101 }

102 FileOutputStream fileOut = new FileOutputStream(Constants.Path_TestData);

103 ExcelWBook.write(fileOut);

104 //fileOut.flush();

105 fileOut.close();

106 ExcelWBook = new XSSFWorkbook(new FileInputStream(Constants.Path_TestData));

107 }catch(Exception e){

108 DriverScript.bResult = false;

109

110 }

111 }

112

113 }

Class: Log

1 package utility;

3 import org.apache.log4j.Logger;

4
5 public class Log {

7 //Initialize Log4j logs

8 private static Logger Log = Logger.getLogger(Log.class.getName());//

10 // This is to print log for the beginning of the test case, as we usually run so many test cases as a test suite

11 public static void startTestCase(String sTestCaseName){

12

13 Log.info("****************************************************************************************");

14 Log.info("****************************************************************************************");

15 Log.info("$$$$$$$$$$$$$$$$$$$$$ "+sTestCaseName+ " $$$$$$$$$$$$$$$$$$$$$$$$$");

16 Log.info("****************************************************************************************");

17 Log.info("****************************************************************************************");

18

19 }

20

21 //This is to print log for the ending of the test case

22 public static void endTestCase(String sTestCaseName){

23 Log.info("XXXXXXXXXXXXXXXXXXXXXXX "+"-E---N---D-"+" XXXXXXXXXXXXXXXXXXXXXX");

24 Log.info("X");

25 Log.info("X");

26 Log.info("X");

27 Log.info("X");

28

29 }

30

31 // Need to create these methods, so that they can be called

32 public static void info(String message) {

33 Log.info(message);

34 }

35

36 public static void warn(String message) {


37 Log.warn(message);

38 }

39

40 public static void error(String message) {

41 Log.error(message);

42 }

43

44 public static void fatal(String message) {

45 Log.fatal(message);

46 }

47

48 public static void debug(String message) {

49 Log.debug(message);

50 }

51

52 }
Project Folder

Você também pode gostar