How To Build a Keyword-driven Framework in Selenium?
Instead of writing the same automation code repeatedly for the same actions, you can create keywords for those actions. When writing tests, you only need to call these keywords. This approach, known as creating a keyword-driven framework, makes test scripts more readable, maintainable, and efficient by avoiding redundancy.
What is a Keyword-driven Framework?
Keyword-driven framework is a framework where test scripts are composed of sequences of keywords. These keywords are code snippets for actions in the system.
For example, an especially common keyword is Click. It instructs the system to simulate a mouse click on a specified web element. The goal is to simplify interactions with the system into a keyword. They become the “building blocks” to help testers compose automated test cases without having to rely heavily on technical knowledge.
Example of Keyword-driven Framework in Action
Let’s look at a snapshot of the keyword library in Katalon Studio:
There are quite a lot of keywords for testers to choose from. Testers only have to choose the keywords for the action they want to perform and string them together to form a complete test case. Keywords can come with parameters, which testers can assign a specific value on which to perform the action.
Let’s say we want to test the following scenario:
Component | Details |
Test Case ID | TC001 |
Description | Verify Login with Valid Credentials |
Preconditions | User is on the Etsy login popup |
Test Steps | 1. Enter a valid email address. 2. Enter the corresponding valid password. 3. Click the "Sign In" button. |
Test Data | Email: validuser@example.com Password: validpassword123 |
Expected Result | Users should be successfully logged in and redirected to the homepage or the previously intended page. |
Actual Result | (To be filled in after execution) |
Postconditions | User is logged in and the session is active |
Pass/Fail Criteria | Pass: Test passes if the user is logged in and redirected correctly. Fail: Test fails if an error message is displayed or the user is not logged in. |
Comments | Ensure the test environment has network access and the server is operational. |
We will need the following keywords for these test steps:
- OpenBrowser [parameter: https://etsy.com]
- Click [parameter: login_button_ID]
- Click [parameter: email_field]
- setText [parameter: username111]
- Click [parameter: password_field]
- setText [parameter: password111]
- Click [parameter: login_form_button_ID]
- VerifyUserLoggedIn
With a collection of diverse keywords, you have a keyword library. You can use version control systems like Git to store and manage the Keyword Library. This helps in tracking changes, collaborating with team members, and maintaining a history of modifications.
Some test automation tools/frameworks also have built-in support for storing and managing keyword libraries within their IDE, such as Robot Framework or Katalon Studio.
Benefits of a Keyword-driven Framework
- Ease of use: once the complexity of coding is abstracted into keywords, even the non-technical people can write and manage tests easily. On another note, this also connects stakeholders (business analysts, project managers, etc.) since it makes testing so much more accessible and understandable to them.
- Support Test Automation: as a result, a keyword-driven framework makes automation testing a breeze. Test cases can now be created quickly just by combining the right keywords and setting parameters for them. These keywords are also highly reusable across test cases, which promotes overall consistency in test design.
- Maintainability: one of the biggest challenges to automation testing is the maintenance. Considering the ever-changing nature of Agile testing, test cases can easily break when changes are made on the UI. Maintaining a large number of test cases is a truly daunting task. With a keyword-driven framework, test cases maintenance is more centralized since testers only need to update the corresponding keyword and not the entire test case.
- Potential Cost and Schedule Savings: all of the benefits mentioned above translate into cost savings for the organization. More functionality can be covered by automated tests, which means higher test coverage, leading to better alignment with Agile best practices.
Challenges of a Keyword-driven Framework
1. Keyword Maintenance: as the application under test evolves, the keywords and their implementations need to be updated to reflect changes in the application’s UI or functionality. This maintenance can become cumbersome, especially if the keyword library is extensive.
2. Complexity in Keyword Design: designing a comprehensive set of keywords that accurately represent all necessary actions and are reusable across different tests is a complex task. You’d need technical expertise to make that happen. Ensuring that keywords are intuitive and cover edge cases requires careful planning and design.
3. Limited Debugging Information: when tests fail, debugging can be challenging because the error messages and logs might not provide sufficient context about which keyword failed or why. This can make it difficult to pinpoint the exact cause of the failure.Increased time and effort may be required to diagnose and resolve issues, impacting the efficiency of the testing process.
4. Performance Overheads: keyword-driven frameworks can introduce performance overhead due to the abstraction layer between the test scripts and the actual test execution. This may result in slower test execution times compared to more direct approaches.
What is Keyword Driven Testing?
Keyword-driven testing is the testing approach that leverages a keyword-driven framework to represent actions in test cases.
Setting Up a Keyword-driven Framework in Selenium
Let’s see how you can set up a keyword-driven framework in Selenium.
- Choose your tool to build it
- Setup environment
- Design framework structure
- Identify keywords and create classes
- Create Page Object Model
- Implement test data handling
- Create keyword executor
Let’s try to create a simple keyword-driven framework in Selenium. The test steps include:
- Open Browser
- Navigate to URL
- Click Sign In Button
- Enter Email
- Enter Password
- Click Sign In
- Verify User Name
- Logout
- Verify Sign In Button
- Close Browser
Step 1: Setup Your Development Environment
First, you need to download and install the latest version of the Java Development Kit from Oracle’s website. You can set the JAVA_HOME environment variable to the JDK installation directory. Here’s a guide to do it from Atlassian.
After that, install Eclipse, IntelliJ IDEA, and then Maven. Make sure to set the M2_HOME and MAVEN_HOME environment variables to the Maven installation directory. After that, add Maven’s bin directory to the PATH environment variable. Here’s a StackOverflow guide to do it.
Once done, open your IDE and create a new Maven project. You can use the maven-archetype-quickstart template to set up the project structure.
Step 2: Add Dependencies To ‘pom.xml’
pom.xml stands for "Project Object Model" XML file. It is the fundamental unit of work in Maven. This file is located in the root directory of a Maven project and it contains information about the project and configuration details used by Maven to build the project.
Maven handles the downloading and linking of libraries required for your project. When you specify a dependency in pom.xml, Maven automatically downloads the necessary library from the specified repository (e.g., Maven Central Repository) and includes it in your project's classpath.
Here’s the dependency you can add to your Maven project:
<dependencies>
<!-- Selenium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<!-- Apache POI for Excel Reading -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- TestNG -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.1.0</version>
<scope>test</scope>
</dependency>
<!-- Log4j for Logging -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
Essentially it includes the Selenium WebDriver library for automating web applications and the Apache POI for Excel readings (these Excel files are where we store our keywords). We also have the TestNG to help write tests and Log4j for Logging results.
You can add more dependencies as you wish to support your testing activities. For example, you can add the Cucumber dependency to run BDD tests or RestAssured to test REST APIs.
Step 3: Create the Directory Structure
The directory structure is essential for organizing your project files in a logical and manageable way. Go to src > main > java
![create a project structure in IntelliJ for Selenium](https://cms-cdn.katalon.com/create_a_project_structure_in_intellij_for_selenium_a5226ec62c.png)
You can set up the following folders:
src/main/java
└── com
└── yourcompany
├── base
├── keywords
├── utils
└── tests
src/test/resources
├── testdata
└── config
Step 4: Create a Keyword Map Table in Excel
Create an Excel sheet that defines all the keywords available for the test automation project. Each row represents a step in a test case, including the keyword, locator, and value if needed.
You can copy this table and paste it into Excel:
Step Number | Keyword | Locator | Value |
1 | openBrowser | ||
2 | navigate | URL | |
3 | clickSignIn_h | //a[@id='signin'] | |
4 | enterEmail | (//div[@class=' css-1wa3eu0-placeholder'])[1] | username |
5 | enterPassword | (//div[@class=' css-1wa3eu0-placeholder'])[2] | password |
6 | clickSignIn | //button[@id='login-btn'] | |
7 | verifyUserName | //span[@class='username'] | username |
8 | logout | //a[@id='logout'] | |
9 | verifySignBtn | //a[@id='signin'] | Sign In |
10 | closeBrowser |
Make sure that the Excel file is formatted correctly, with columns for each component of the test steps.
Step 5: Organize Project Structure
In your Java IDE (such as Eclipse, IntelliJ IDEA, etc.), locate your project in the project explorer panel. After that, right-click on your project and navigate to New > Package. Name the package excelData.
This package will serve as a dedicated folder within your project to store data files, particularly your Excel file.
Once done, copy the Excel file (DemoFile.xlsx) and paste it into the excelData directory.
ProjectName
├── src
│ ├── main
│ │ ├── java
│ │ │ ├── com
│ │ │ │ ├── keyword_driven_framework
│ │ │ │ │ ├── utility
│ │ │ │ │ ├── keywordDriven
│ │ │ │ │ ├── excelUtility
│ │ │ │ │ ├── executionEngine
│ │ ├── resources
│ │ │ ├── excelData
│ │ │ │ ├── DemoFile.xlsx
Placing the Excel file within the project structure allows for easy access by the code that will read from this file, ensuring that file paths are relative to the project and reducing potential file path errors.
Step 6: Create a Constants Class
Create a new package named utility and define constants like URL, filePath, and Excel data in a class named Constants. These constants can be accessed throughout your project to maintain consistency and easily make changes in one place if needed.
package com.keyword_driven_framework.utility;
public class Constants {
public static final String URL = "https://bstackdemo.com/";
public static final String filePath = "D:\\DemoFile.xlsx";
public static final String excelData = "DemoFile.xlsx";
public static final String username = "Your_Username";
public static final String password = "Your_password";
}
Step 7: Implement Action Keywords
Create a new package named keywordDriven and define methods for each action keyword in a class named Action_Keyword.
package com.keyword_driven_framework.keywordDriven;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import com.keyword_driven_framework.utility.Constants;
public class Action_keyword {
public static WebDriver driver;
public void openBrowser() {
System.setProperty("webdriver.gecko.driver", "path_to_driver");
FirefoxOptions options = new FirefoxOptions();
driver = new FirefoxDriver(options);
driver.manage().window().maximize();
}
public void navigate() {
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.get(Constants.URL);
}
public void clickSignIn_h() {
driver.findElement(By.xpath("//a[@id='signin']")).click();
}
public void enterEmail() {
driver.findElement(By.xpath("(//div[@class=' css-1wa3eu0-placeholder'])[1]")).sendKeys(Constants.username);
}
public void enterPassword() {
driver.findElement(By.xpath("(//div[@class=' css-1wa3eu0-placeholder'])[2]")).sendKeys(Constants.password);
}
public void clickSignIn() {
driver.findElement(By.xpath("//button[@id='login-btn']")).click();
}
public void verifyUserName() {
String username = "your_username";
username.equals(driver.findElement(By.xpath("//span[@class='username']")).getText());
}
public void logout() {
driver.findElement(By.xpath("//a[@id='logout']")).click();
}
public void verifySignBtn() {
String signIn = "Sign In";
signIn.equals(driver.findElement(By.xpath("//a[@id='signin']")).getText());
}
public void closeBrowser() {
driver.quit();
}
}
Step 8: Implement Action Keywords
This step is when you create a dedicated package in your project to house the classes and methods that will execute the action keywords defined in your Excel file.
To do this, create another package named keywordDriven. Within it create a class file named Action_Keyword.
In the Action_Keyword class, define methods for each action keyword identified in your Excel file. Each method will correspond to an action (e.g., open browser, navigate, click, enter text). For example:
package com.keyword_driven_framework.keywordDriven;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import com.keyword_driven_framework.utility.Constants;
public class Action_Keyword {
public static WebDriver driver;
public void openBrowser() {
// Set the path to the WebDriver executable
System.setProperty("webdriver.gecko.driver", "path_to_driver");
// Create a new instance of the Firefox driver
FirefoxOptions options = new FirefoxOptions();
driver = new FirefoxDriver(options);
// Maximize the browser window
driver.manage().window().maximize();
}
public void navigate() {
// Implicit wait
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// Navigate to the URL
driver.get(Constants.URL);
}
public void clickSignIn_h() {
// Locate and click the Sign In button
driver.findElement(By.xpath("//a[@id='signin']")).click();
}
public void enterEmail() {
// Locate the email field and enter the email
driver.findElement(By.xpath("(//div[@class=' css-1wa3eu0-placeholder'])[1]")).sendKeys(Constants.username);
}
public void enterPassword() {
// Locate the password field and enter the password
driver.findElement(By.xpath("(//div[@class=' css-1wa3eu0-placeholder'])[2]")).sendKeys(Constants.password);
}
public void clickSignIn() {
// Locate and click the Sign In button
driver.findElement(By.xpath("//button[@id='login-btn']")).click();
}
public void verifyUserName() {
// Verify the username
String username = "your_username";
username.equals(driver.findElement(By.xpath("//span[@class='username']")).getText());
}
public void logout() {
// Locate and click the Logout button
driver.findElement(By.xpath("//a[@id='logout']")).click();
}
public void verifySignBtn() {
// Verify the Sign In button is present
String signIn = "Sign In";
signIn.equals(driver.findElement(By.xpath("//a[@id='signin']")).getText());
}
public void closeBrowser() {
// Close the browser
driver.quit();
}
}
Here we have defined the following keywords:
- openBrowser
- Navigate
- slickSignIn_h
- enterEmail
- enterPassword
- clickSignIn
- verifyUsername
- logout
- verifySignBtn
- closeBrowser
By building this class, you promote code reuse and modularity. It becomes much easier to maintain and update the framework when the action methods are organized in a structured manner.
Step 9: Read Data From Excel
This step allows the framework to dynamically read the keywords, locators, and values from your previously created Excel sheet. Since it is extracting data from an external source rather than hardcoding them into the test scripts, the framework is more flexible, maintainable, and scalable.
Here we’ll create another class named ReadExcelSheet. In this class, we can define methods to read the keywords, locators, and values from the Excel sheet and store them in a suitable data structure (e.g., ArrayList).
Here’s how the class might look like:
package com.keyword_driven_framework.excelUtility;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.keyword_driven_framework.utility.Constants;
public class ReadExcelSheet {
public ArrayList<String> readExcelData(int colNo) throws IOException {
String filePath = Constants.filePath;
File file = new File(filePath);
// Create an object of FileInputStream class and pass file as parameter to its constructor.
FileInputStream fis = new FileInputStream(file);
// Create a workbook instance that refers to the Excel file.
XSSFWorkbook wb = new XSSFWorkbook(fis);
// Get the desired sheet from the workbook.
XSSFSheet sheet = wb.getSheet("Sheet1");
// Create an iterator to iterate through the rows of the sheet.
Iterator<Row> rowIterator = sheet.iterator();
// Skip the header row.
rowIterator.next();
// Create an ArrayList to store the data.
ArrayList<String> data = new ArrayList<>();
// Iterate through the rows.
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
// Get the cell at the specified column index.
Cell cell = row.getCell(colNo);
// Get the cell value as a string.
String cellValue = cell.getStringCellValue();
// Add the cell value to the ArrayList.
data.add(cellValue);
}
// Close the workbook and file input stream.
wb.close();
fis.close();
// Print and return the data.
System.out.println("List: " + data);
return data;
}
}
Step 10: Build The Execution Engine
Finally, we’ll create another package named executionEngine in which we’ll have a class with the same name. It will be the main driver of your keyword-driven framework. It will read the keywords, locators, and values from the Excel sheet and invoke the corresponding methods in the Action_Keyword class.
package com.keyword_driven_framework.executionEngine;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.keyword_driven_framework.excelUtility.ReadExcelSheet;
import com.keyword_driven_framework.keywordDriven.Action_keyword;
public class ExecutionTest {
public static void main(String[] args) throws IOException, Exception, IllegalArgumentException, InvocationTargetException {
ReadExcelSheet rs = new ReadExcelSheet();
Action_keyword actions = new Action_keyword();
Class<Action_keyword> actionClass = Action_keyword.class;
ArrayList<String> keywords = rs.readExcelData(1);
ArrayList<String> locators = rs.readExcelData(2);
ArrayList<String> values = rs.readExcelData(3);
for (int i = 0; i < keywords.size(); i++) {
String methodName = keywords.get(i);
String locator = locators.get(i);
String value = values.get(i);
Method method;
if (locator != null && !locator.isEmpty() && value != null && !value.isEmpty()) {
method = actionClass.getMethod(methodName, String.class, String.class);
method.invoke(actions, locator, value);
} else if (locator != null && !locator.isEmpty()) {
method = actionClass.getMethod(methodName, String.class);
method.invoke(actions, locator);
} else {
method = actionClass.getMethod(methodName);
method.invoke(actions);
}
}
System.out.println("Test executed successfully");
}
}
Run the ExecutionTest class to observe the output. The framework will read the keywords and corresponding data from the Excel sheet and execute the automated test steps accordingly.
Keyword-driven Testing With Automation Testing Tools
To skip the hassle of building and maintaining a framework, you can shop around for an automation testing tool that comes with a keyword-driven framework built-in that is ready-to-use immediately.