Certainly! Based on the extensive transcript you’ve provided, we’ll continue building a comprehensive guide on Data-Driven Testing (DDT) Using Excel and Properties Files with Selenium WebDriver in Java. This section will delve into the practical implementation of DDT, including creating utility files, handling Excel operations, working with properties files, and executing test cases using Selenium WebDriver.
Table of Contents
1. Introduction to Data-Driven Testing
Data-Driven Testing (DDT) is a testing methodology where test scripts are executed multiple times with different sets of input data. This approach enhances test coverage and efficiency by separating test logic from test data. In Selenium WebDriver with Java, Excel files are commonly used to store and manage test data.
1.1. What is Data-Driven Testing?
Data-Driven Testing involves the following steps:
- Preparing Test Data: Organize test data in external sources like Excel files.
- Reading Test Data: Use automation scripts to read data from these sources.
- Executing Tests: Pass the read data to the application under test.
- Validating Results: Verify the application’s behavior based on the input data.
Benefits of DDT:
- Reusability: Test scripts can be reused with different data sets.
- Scalability: Easily expand test coverage by adding more data without modifying scripts.
- Maintainability: Simplifies maintenance by separating data from test logic.
2. Understanding Excel File Structure
Before diving into automation, it’s essential to understand the structure of Excel files. Excel organizes data hierarchically as follows:
Excel File (.xls or .xlsx)
│
└── Workbook
│
├── Sheet (Worksheet)
│ │
│ ├── Row
│ │ │
│ │ └── Cell
│ │
│ └── ...
│
└── ...
Key Components:
- Excel File: The entire document containing one or more workbooks.
- Workbook: A collection of one or more sheets.
- Sheet (Worksheet): A single tab within a workbook, containing rows and cells.
- Row: A horizontal grouping of cells.
- Cell: The intersection of a row and a column, holding individual data points.
Hierarchy Flow:
Excel File → Workbook → Sheet → Row → Cell
3. Setting Up Apache POI with Maven
Apache POI is a powerful Java library for interacting with Microsoft Office documents, including Excel files. Since Selenium WebDriver does not natively support Excel operations, integrating Apache POI is essential for Data-Driven Testing.
3.1. Integrating Apache POI with Maven
If your project uses Maven for dependency management, follow these steps to add Apache POI:
- Locate the Maven Repository:Visit the Maven Repository to find the necessary Apache POI dependencies.
- Add Dependencies to
pom.xml
:Include the following dependencies in your project’spom.xml
file:<!-- Apache POI Core --> org.apache.poi poi 5.2.5 <!-- Use the latest stable version --> <!-- Apache POI for OOXML (Required for .xlsx files) --> org.apache.poi poi-ooxml 5.2.5 <!-- Use the latest stable version --> <!-- Apache Log4j for Logging (Optional but recommended) --> org.apache.logging.log4j log4j-core 2.17.1 <!-- Use the latest stable version -->
Note:
- Ensure that the versions match the latest stable releases to avoid compatibility issues.
- Adding Log4j is optional but helps in managing logging effectively.
- Refresh Maven Project:After adding the dependencies, refresh your Maven project to download and include the new libraries.
Understanding Dependencies:
- poi: Core library for working with Excel files.
- poi-ooxml: Extends POI to handle OOXML formats like .xlsx.
- log4j-core: Facilitates logging, helping to manage and debug your automation scripts.
4. Reading Data from Excel Files
Reading data from Excel files involves navigating through the Excel hierarchy to access specific cells. Here’s a step-by-step guide with sample code.
4.1. Prerequisites:
- An existing Excel file (
data.xlsx
) with test data. - Properly configured Apache POI dependencies in your Maven project.
4.2. Step-by-Step Implementation
- Open the Excel File in Reading Mode:
FileInputStream fileInputStream = new FileInputStream("path_to_your_excel_file/data.xlsx");
Explanation:
- FileInputStream from
java.io
is used to read the Excel file. - Replace
"path_to_your_excel_file/data.xlsx"
with the actual path to your Excel file.
- FileInputStream from
- Create a Workbook Instance:
XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
Explanation:
- XSSFWorkbook represents the entire workbook.
- It is initialized with the
FileInputStream
to access the Excel file’s contents.
- Access a Specific Sheet:
XSSFSheet sheet = workbook.getSheet("Sheet1"); // Replace "Sheet1" with your sheet name
Explanation:
getSheet(String name)
retrieves the sheet by its name.- Alternatively, you can use
getSheetAt(int index)
to access a sheet by its index (starting from 0).
- Determine the Number of Rows and Cells:
int totalRows = sheet.getLastRowNum(); // Returns the index of the last row Row firstRow = sheet.getRow(0); // Assuming the first row is the header int totalCells = firstRow.getLastCellNum(); // Returns the number of cells in the first row
Explanation:
getLastRowNum()
returns the index of the last row (0-based index).getRow(int rownum)
retrieves a specific row.getLastCellNum()
returns the number of cells in the row.
- Iterate Through Rows and Cells to Read Data:
for (int r = 1; r <= totalRows; r++) { // Start from 1 if row 0 is header Row currentRow = sheet.getRow(r); for (int c = 0; c < totalCells; c++) { Cell currentCell = currentRow.getCell(c); String cellData = currentCell.toString(); // Converts cell data to String System.out.print(cellData + "\t"); } System.out.println(); }
Explanation:
- Outer Loop (for (int r = 1; r <= totalRows; r++)): Iterates through each row, starting from 1 to skip headers.
- Inner Loop (for (int c = 0; c < totalCells; c++)): Iterates through each cell in the current row.
- currentCell.toString(): Converts the cell’s content to a string, regardless of its original data type.
- Output Formatting: Uses tab (
\t
) and newline (\n
) for readable console output.
- Closing Resources:
workbook.close(); fileInputStream.close();
Explanation:
- Always close Workbook and FileInputStream to free up resources and avoid memory leaks.
4.3. Sample Code: Reading Excel Data
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 java.io.FileInputStream;
import java.io.IOException;
public class ExcelDataReader {
public static void main(String[] args) {
String filePath = System.getProperty("user.dir") + "/testdata/data.xlsx"; // Dynamic path
try {
// 1. Open the Excel file
FileInputStream fileInputStream = new FileInputStream(filePath);
// 2. Create Workbook instance
XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
// 3. Access the sheet
XSSFSheet sheet = workbook.getSheet("Sheet1"); // Replace with your sheet name
// 4. Get total number of rows and cells
int totalRows = sheet.getLastRowNum();
Row firstRow = sheet.getRow(0);
int totalCells = firstRow.getLastCellNum();
System.out.println("Total Rows: " + totalRows);
System.out.println("Total Cells: " + totalCells);
// 5. Iterate through rows and cells
for (int r = 1; r <= totalRows; r++) { // Start from 1 to skip header
Row currentRow = sheet.getRow(r);
for (int c = 0; c < totalCells; c++) {
Cell currentCell = currentRow.getCell(c);
String cellData = currentCell.toString();
System.out.print(cellData + "\t");
}
System.out.println();
}
// 6. Close resources
workbook.close();
fileInputStream.close();
} catch (IOException e) {
System.out.println("An error occurred while reading the Excel file.");
e.printStackTrace();
}
}
}
Output Example:
Total Rows: 5
Total Cells: 4
Java 2023-10-10 200 New York
Python 2023-10-11 300 Los Angeles
C# 2023-10-12 400 Chicago
...
4.4 Handling Common Issues:
- Log4j Errors:If you encounter errors related to Log4j (e.g., “Could not find a valid logging implementation”), ensure that you’ve added the necessary Log4j dependencies in your
pom.xml
. This step is optional but recommended for effective logging. - Indexing Errors:Remember that both row and cell indices start from 0. Ensure your loops reflect this to avoid
NullPointerException
orIndexOutOfBoundsException
.
5. Writing Data to Excel Files
Writing data to Excel involves creating new workbooks, sheets, rows, and cells, and populating them with data. Here’s how you can achieve this using Apache POI.
5.1. Prerequisites:
- No existing Excel file is required; the script can create a new one.
- Properly configured Apache POI dependencies in your Maven project.
5.2. Step-by-Step Implementation
- Create a New Excel File in Writing Mode:
FileOutputStream fileOutputStream = new FileOutputStream("path_to_your_excel_file/newdata.xlsx");
Explanation:
- FileOutputStream from
java.io
is used to write data to a new Excel file. - If the file does not exist, it will be created automatically.
- FileOutputStream from
- Create a Workbook Instance:
XSSFWorkbook workbook = new XSSFWorkbook();
Explanation:
- Initializes a new workbook where you’ll create sheets, rows, and cells.
- Create a Sheet:
XSSFSheet sheet = workbook.createSheet("Data");
Explanation:
createSheet(String name)
creates a new sheet with the specified name.
- Create Rows and Cells with Data:
// Creating the first row (Row 0) Row row0 = sheet.createRow(0); Cell cell0_0 = row0.createCell(0); cell0_0.setCellValue("Java"); Cell cell0_1 = row0.createCell(1); cell0_1.setCellValue("2023-10-10"); Cell cell0_2 = row0.createCell(2); cell0_2.setCellValue(200); Cell cell0_3 = row0.createCell(3); cell0_3.setCellValue("New York"); // Repeat for additional rows as needed
Explanation:
createRow(int rownum)
creates a new row at the specified index.createCell(int cellnum)
creates a new cell in the row at the specified index.setCellValue()
assigns a value to the cell. It is overloaded to accept different data types (e.g., String, int, double).
- Writing Data Dynamically Using Loops:To write dynamic data provided by the user at runtime, utilize nested loops.
Scanner scanner = new Scanner(System.in); System.out.print("Enter number of rows: "); int numberOfRows = scanner.nextInt(); System.out.print("Enter number of cells per row: "); int numberOfCells = scanner.nextInt(); scanner.nextLine(); // Consume newline for (int r = 0; r < numberOfRows; r++) { Row currentRow = sheet.createRow(r); for (int c = 0; c < numberOfCells; c++) { Cell currentCell = currentRow.createCell(c); System.out.print("Enter data for Row " + r + ", Cell " + c + ": "); String cellData = scanner.nextLine(); currentCell.setCellValue(cellData); } }
Explanation:
- Outer Loop (for (int r = 0; r < numberOfRows; r++)): Creates rows based on user input.
- Inner Loop (for (int c = 0; c < numberOfCells; c++)): Creates cells within each row and populates them with user-provided data.
- Scanner: Captures user input from the console.
- Write Workbook to File and Close Resources:
workbook.write(fileOutputStream); workbook.close(); fileOutputStream.close(); scanner.close();
Explanation:
workbook.write(OutputStream out)
: Writes the workbook data to the specified output stream.- Always close Workbook, FileOutputStream, and Scanner objects to free up resources.
5.3. Sample Code: Writing Excel Data
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 java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class ExcelDataWriter {
public static void main(String[] args) {
String filePath = System.getProperty("user.dir") + "/testdata/newdata.xlsx"; // Dynamic path
try {
// 1. Create a new Excel file
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
// 2. Create Workbook instance
XSSFWorkbook workbook = new XSSFWorkbook();
// 3. Create a sheet named "Data"
XSSFSheet sheet = workbook.createSheet("Data");
// 4. Create Rows and Cells with Static Data
Row row0 = sheet.createRow(0);
Cell cell0_0 = row0.createCell(0);
cell0_0.setCellValue("Java");
Cell cell0_1 = row0.createCell(1);
cell0_1.setCellValue("2023-10-10");
Cell cell0_2 = row0.createCell(2);
cell0_2.setCellValue(200);
Cell cell0_3 = row0.createCell(3);
cell0_3.setCellValue("New York");
// 5. Create Rows and Cells with Dynamic Data
Scanner scanner = new Scanner(System.in);
System.out.print("Enter number of rows to create: ");
int numberOfRows = scanner.nextInt();
System.out.print("Enter number of cells per row: ");
int numberOfCells = scanner.nextInt();
scanner.nextLine(); // Consume newline
for (int r = 1; r <= numberOfRows; r++) { // Start from 1 to continue after static data
Row currentRow = sheet.createRow(r);
for (int c = 0; c < numberOfCells; c++) {
Cell currentCell = currentRow.createCell(c);
System.out.print("Enter data for Row " + r + ", Cell " + c + ": ");
String cellData = scanner.nextLine();
currentCell.setCellValue(cellData);
}
}
// 6. Write the workbook to the file
workbook.write(fileOutputStream);
// 7. Close resources
workbook.close();
fileOutputStream.close();
scanner.close();
System.out.println("Excel file written successfully!");
} catch (IOException e) {
System.out.println("An error occurred while writing to the Excel file.");
e.printStackTrace();
}
}
}
Sample Interaction:
Enter number of rows to create: 2
Enter number of cells per row: 3
Enter data for Row 1, Cell 0: Python
Enter data for Row 1, Cell 1: 2023-10-11
Enter data for Row 1, Cell 2: 300
Enter data for Row 2, Cell 0: C#
Enter data for Row 2, Cell 1: 2023-10-12
Enter data for Row 2, Cell 2: 400
Excel file written successfully!
Resulting newdata.xlsx
:
Java 2023-10-10 200 New York
Python 2023-10-11 300
C# 2023-10-12 400
5.4 Handling Common Issues:
- File Overwrite Warning:When writing to an existing file,
FileOutputStream
will overwrite it. Ensure you’re not unintentionally overwriting important data. - Data Types:
setCellValue()
is overloaded to handle different data types (String, double, boolean, etc.). Use the appropriate method based on the data type you intend to write.
6. Best Practices and Tips
6.1. Dynamic Path Handling
Use System.getProperty("user.dir")
:
String filePath = System.getProperty("user.dir") + "/testdata/data.xlsx";
6.2. Exception Handling
- Comprehensive Try-Catch Blocks:Enclose file operations within try-catch blocks to handle
IOExceptions
and prevent abrupt script termination. - Resource Management:Always close
Workbook
,FileInputStream
,FileOutputStream
, andScanner
objects in thefinally
block or use try-with-resources for automatic closure.
6.3. Utility Classes for Reusability
Create a Utility Class:
public class ExcelUtils {
public static XSSFWorkbook getWorkbook(String filePath) throws IOException {
FileInputStream fis = new FileInputStream(filePath);
return new XSSFWorkbook(fis);
}
public static XSSFSheet getSheet(XSSFWorkbook workbook, String sheetName) {
return workbook.getSheet(sheetName);
}
public static Row getRow(XSSFSheet sheet, int rowIndex) {
return sheet.getRow(rowIndex);
}
public static Cell getCell(Row row, int cellIndex) {
return row.getCell(cellIndex);
}
// Add more utility methods as needed
}
6.4. Data Validation
Validate Excel Data:
- Before using the data in your tests, validate it to ensure correctness and completeness, reducing the risk of test failures due to data issues.
6.5. Avoid Hardcoding Paths
Use Dynamic Paths:
String filePath = System.getProperty("user.dir") + "/testdata/data.xlsx";
6.6. Logging and Reporting
Implement Logging:
- Use logging frameworks like Log4j to capture detailed logs, aiding in debugging and monitoring test executions.
6.7. Consistent Naming Conventions
- Use Descriptive Names: Name your sheets, rows, and cells descriptively to make the data easily understandable.
7. Conclusion
Mastering Data-Driven Testing using Excel files with Selenium WebDriver and Apache POI in Java is pivotal for creating robust and scalable automated tests. By understanding the Excel file structure, effectively integrating Apache POI, and implementing best practices, you can efficiently manage and utilize test data, enhancing your testing strategy’s effectiveness.
Recap of Key Concepts:
- Data-Driven Testing: Separates test data from test logic, allowing for multiple test iterations with varying data sets.
- Excel File Structure: Hierarchical organization from Excel File → Workbook → Sheet → Row → Cell.
- Apache POI Integration: Enables reading from and writing to Excel files within Java-based Selenium projects.
- Reading and Writing Operations: Utilize Apache POI classes and methods to interact with Excel data programmatically.
- Best Practices: Emphasize dynamic path handling, exception management, utility classes, and logging for efficient automation scripting.
Next Steps:
- Implement Utility Classes: Create reusable utility classes to handle Excel operations, streamlining your Data-Driven Testing approach.
- Integrate with Test Frameworks: Combine Data-Driven Testing with frameworks like TestNG or JUnit to enhance test management and reporting.
- Explore Advanced Apache POI Features: Delve deeper into Apache POI to handle complex Excel operations, such as formatting, styling, and managing large datasets.
- Automate Data Validation: Incorporate data validation steps to ensure the integrity and accuracy of your test data before executing tests.
Happy Testing! 🚀
8. Practical Implementation of Data-Driven Testing
In this section, we’ll walk through the practical steps of implementing Data-Driven Testing using the utility files we previously created. We’ll cover:
- Creating a Data-Driven Test Case
- Handling Excel Operations with Utility Methods
- Integrating Properties Files for Configuration Management
- Executing and Validating Test Cases
- Best Practices and Troubleshooting
8.1. Creating a Data-Driven Test Case
To illustrate Data-Driven Testing, we’ll automate a Fixed Deposit (FD) Calculator application. The test case involves:
- Launching the Application
- Reading Test Data from Excel
- Entering Data into the Application
- Validating the Maturity Value
- Writing Results Back to Excel
- Handling Positive and Negative Scenarios
8.1.1. Understanding the Test Case
Scenario: Fixed Deposit (FD) Calculator
- Inputs:
- Principal Amount
- Rate of Interest
- Period (Number and Type: Days, Months, Years)
- Frequency (Simple Interest)
- Process:
- Enter the input data.
- Click on the “Calculate” button.
- Outputs:
- Maturity Value: The calculated amount based on the inputs.
- Validation:
- Compare the calculated maturity value with the expected value.
- Update the result (“Pass” or “Fail”) in the Excel sheet.
8.1.2. Preparing Test Data
Create an Excel file named FDData.xlsx
in the testdata
folder with the following structure:
Principal Amount Rate of Interest Period Period Type Frequency Expected Maturity Value
10000 5 2 Years Simple 11000
15000 4.5 1 Years Simple 15750
20000 6 3 Years Simple 23600
25000 5.5 2 Years Simple 27625
30000 5 2 Years Simple 33000
35000 4 1 Months Simple 35350
Notes:
- The first five rows contain positive scenarios where the expected maturity value is correctly calculated.
- The last row introduces a negative scenario with an incorrect expected maturity value to validate failure handling.
8.2. Handling Excel Operations with Utility Methods
Utilize the previously created ExcelUtils
class to manage Excel operations efficiently. This approach avoids code duplication and enhances maintainability.
8.2.1. Recap of ExcelUtils Methods
- getRowCount(String filePath, String sheetName): int
- Returns the total number of rows in a specified sheet.
- getCellCount(String filePath, String sheetName, int rowNum): int
- Returns the total number of cells in a specified row.
- getCellData(String filePath, String sheetName, int rowNum, int cellNum): String
- Retrieves data from a specific cell.
- setCellData(String filePath, String sheetName, int rowNum, int cellNum, String data): void
- Writes data to a specific cell.
- fillGreenColor(String filePath, String sheetName, int rowNum, int cellNum): void
- Applies green color to a specific cell (optional).
- fillRedColor(String filePath, String sheetName, int rowNum, int cellNum): void
- Applies red color to a specific cell (optional).
8.3. Integrating Properties Files for Configuration Management
Properties files are essential for managing configuration data such as application URLs, credentials, and other constants. This integration ensures that any changes to configuration data don’t require modifying the test scripts themselves.
8.3.1. Creating the config.properties
File
Place the config.properties
file in the testdata
folder with the following content:
appURL=http://example.com/fdcalculator
email=your_email@example.com
password=your_password
orderID=ORD12345
customerID=CUST67890
Key-Value Pairs:
- appURL: The URL of the FD Calculator application.
- email: Test email address.
- password: Test password.
- orderID: Example order ID.
- customerID: Example customer ID.
8.3.2. Reading Properties Files
We’ll use the Properties
class in Java to read data from the config.properties
file. Here’s how to implement it:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class ConfigReader {
public static Properties readProperties(String filePath) {
Properties properties = new Properties();
try {
FileInputStream fis = new FileInputStream(filePath);
properties.load(fis);
fis.close();
} catch (IOException e) {
System.out.println("An error occurred while reading the properties file.");
e.printStackTrace();
}
return properties;
}
public static void main(String[] args) {
String filePath = System.getProperty("user.dir") + "/testdata/config.properties";
Properties config = readProperties(filePath);
String appURL = config.getProperty("appURL");
String email = config.getProperty("email");
String password = config.getProperty("password");
String orderID = config.getProperty("orderID");
String customerID = config.getProperty("customerID");
System.out.println("Application URL: " + appURL);
System.out.println("Email: " + email);
System.out.println("Password: " + password);
System.out.println("Order ID: " + orderID);
System.out.println("Customer ID: " + customerID);
}
}
Explanation:
- readProperties(String filePath): Properties
- Purpose: Reads the properties file and returns a Properties object containing key-value pairs.
- Parameters:
filePath:
The dynamic path to theconfig.properties
file.
- main Method:
- Demonstrates how to use the
readProperties
method to retrieve configuration data. - Prints the retrieved values to the console for verification.
- Demonstrates how to use the
Output Example:
Application URL: http://example.com/fdcalculator
Email: your_email@example.com
Password: your_password
Order ID: ORD12345
Customer ID: CUST67890
Best Practices:
- Centralized Configuration: Keep all configuration data in the properties file to avoid hardcoding values in test scripts.
- Security: Avoid storing sensitive information (like passwords) in plain text. Consider using encryption or environment variables for sensitive data.
- Dynamic Path Handling: Use
System.getProperty("user.dir")
to construct dynamic paths, enhancing portability across different environments.
8.4. Executing and Validating Test Cases
With the utility files and configuration management in place, we can now create and execute our Data-Driven Test Case for the FD Calculator.
8.4.1. Creating the FD Calculator Test Case
Create a new Java class named FDCalculatorTest
in your test package. This class will contain the automation script to execute the DDT.
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;
import java.util.Properties;
public class FDCalculatorTest {
public static void main(String[] args) {
// Step 1: Initialize WebDriver
System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");
WebDriver driver = new ChromeDriver();
// Step 2: Maximize Browser and Navigate to Application URL
driver.manage().window().maximize();
// Read properties file
String configFilePath = System.getProperty("user.dir") + "/testdata/config.properties";
Properties config = ConfigReader.readProperties(configFilePath);
String appURL = config.getProperty("appURL");
driver.get(appURL);
// Excel file path
String excelFilePath = System.getProperty("user.dir") + "/testdata/FDData.xlsx";
String sheetName = "Sheet1";
// Get row count
int rowCount = ExcelUtils.getRowCount(excelFilePath, sheetName);
System.out.println("Total Rows: " + rowCount);
// Iterate through each row (starting from 1 to skip header)
for (int i = 1; i <= rowCount; i++) {
try {
// Step 3: Read Data from Excel
String principal = ExcelUtils.getCellData(excelFilePath, sheetName, i, 0);
String rateOfInterest = ExcelUtils.getCellData(excelFilePath, sheetName, i, 1);
String period = ExcelUtils.getCellData(excelFilePath, sheetName, i, 2);
String periodType = ExcelUtils.getCellData(excelFilePath, sheetName, i, 3);
String frequency = ExcelUtils.getCellData(excelFilePath, sheetName, i, 4);
String expectedMaturity = ExcelUtils.getCellData(excelFilePath, sheetName, i, 5);
// Step 4: Enter Data into Application
WebElement principalField = driver.findElement(By.xpath("//input[@id='principal']"));
principalField.clear();
principalField.sendKeys(principal);
WebElement roiField = driver.findElement(By.xpath("//input[@id='rate']"));
roiField.clear();
roiField.sendKeys(rateOfInterest);
WebElement periodField = driver.findElement(By.xpath("//input[@id='period']"));
periodField.clear();
periodField.sendKeys(period);
Select periodDropdown = new Select(driver.findElement(By.xpath("//select[@id='periodType']")));
periodDropdown.selectByVisibleText(periodType);
Select frequencyDropdown = new Select(driver.findElement(By.xpath("//select[@id='frequency']")));
frequencyDropdown.selectByVisibleText(frequency);
// Step 5: Click Calculate
WebElement calculateButton = driver.findElement(By.xpath("//button[@id='calculate']"));
calculateButton.click();
// Wait for calculation to complete
Thread.sleep(3000);
// Step 6: Capture Actual Maturity Value
WebElement maturityValueElement = driver.findElement(By.xpath("//span[@id='maturityValue']/strong"));
String actualMaturity = maturityValueElement.getText();
// Step 7: Validate Maturity Value
double expected = Double.parseDouble(expectedMaturity);
double actual = Double.parseDouble(actualMaturity.replace("$", ""));
if (expected == actual) {
System.out.println("Test Case " + i + ": Passed");
ExcelUtils.setCellData(excelFilePath, sheetName, i, 6, "Pass");
ExcelUtils.fillGreenColor(excelFilePath, sheetName, i, 6);
} else {
System.out.println("Test Case " + i + ": Failed");
ExcelUtils.setCellData(excelFilePath, sheetName, i, 6, "Fail");
ExcelUtils.fillRedColor(excelFilePath, sheetName, i, 6);
}
// Step 8: Clear Data for Next Iteration
WebElement clearButton = driver.findElement(By.xpath("//button[@id='clear']"));
clearButton.click();
// Wait after clearing
Thread.sleep(2000);
} catch (Exception e) {
System.out.println("An error occurred in Test Case " + i);
e.printStackTrace();
}
}
// Step 9: Close Browser
driver.quit();
}
}
Explanation:
- WebDriver Initialization:
- Set the system property for ChromeDriver.
- Instantiate the ChromeDriver and maximize the browser window.
- Navigate to the FD Calculator application URL obtained from the properties file.
- Excel Operations:
- Define the path to the
FDData.xlsx
file. - Retrieve the total number of rows to determine the number of test iterations.
- Define the path to the
- Test Iterations:
- Loop through each row of the Excel sheet (excluding the header).
- Read Data: Extract input values and expected maturity value from Excel using
ExcelUtils
. - Enter Data: Locate web elements using XPath and input the extracted data.
- Calculate: Click the “Calculate” button and wait for the calculation to complete.
- Capture Actual Maturity Value: Retrieve the calculated maturity value from the application.
- Validate: Compare the actual maturity value with the expected value.
- If they match, mark the test case as “Pass” and fill the cell with green color.
- If they don’t match, mark it as “Fail” and fill the cell with red color.
- Clear Data: Click the “Clear” button to reset the form for the next iteration.
- Exception Handling:
- Encapsulate each iteration within a try-catch block to handle any unexpected errors without terminating the entire test suite.
- Cleanup:
- After all iterations, close the browser using
driver.quit()
to end the session.
- After all iterations, close the browser using
8.4.2. Handling Data Types and Formatting
- Maturity Value Comparison:
- The maturity values are in string format with a dollar sign (e.g., $11000).
- Use
replace("$", "")
to remove the dollar sign before parsing to double.
- Thread Sleep:
Thread.sleep(3000);
pauses the execution for 3 seconds to allow the calculation to complete.- Adjust the sleep duration based on the application’s response time.
8.4.3. Executing the Test Case
- Ensure All Files Are Closed:
- Close the
FDData.xlsx
andconfig.properties
files to prevent file locking issues during execution.
- Close the
- Run the Test Script:
- Execute the
FDCalculatorTest
class. - Observe the console for “Passed” or “Failed” messages corresponding to each test case.
- Execute the
- Verify Excel Results:
- Open the
FDData.xlsx
file post-execution. - Check the “Expected Maturity Value” and “Result” columns to ensure they reflect the test outcomes.
- Cells marked “Pass” should be filled with green, and “Fail” with red.
- Open the
Sample Console Output:
Total Rows: 6
Test Case 1: Passed
Test Case 2: Passed
Test Case 3: Passed
Test Case 4: Passed
Test Case 5: Passed
Test Case 6: Failed
Sample Excel Output:
Principal Amount Rate of Interest Period Period Type Frequency Expected Maturity Value Result
10000 5 2 Years Simple 11000 Pass
15000 4.5 1 Years Simple 15750 Pass
20000 6 3 Years Simple 23600 Pass
25000 5.5 2 Years Simple 27625 Pass
30000 5 2 Years Simple 33000 Pass
35000 4 1 Months Simple 35350 Fail
Notes:
- The sixth test case is designed to fail to validate negative scenarios.
- The Result column is automatically updated based on the validation.
8.5. Best Practices and Troubleshooting
8.5.1. Best Practices
- Use Dynamic Paths:
- Always construct file paths dynamically using
System.getProperty("user.dir")
to ensure portability.
- Always construct file paths dynamically using
- Centralize Configuration:
- Store all configuration data in properties files to avoid hardcoding and simplify maintenance.
- Modularize Code:
- Use utility classes (
ExcelUtils
,ConfigReader
) to encapsulate repetitive tasks, enhancing reusability and readability.
- Use utility classes (
- Implement Robust Exception Handling:
- Use try-catch blocks to handle unexpected issues without halting the entire test suite.
- Validate Data Types:
- Ensure that data types are correctly handled, especially when converting between strings and numeric types.
- Use Explicit Waits:
- Instead of
Thread.sleep()
, consider using Selenium’sWebDriverWait
for more efficient and reliable waits.
- Instead of
- Maintain Clear Naming Conventions:
- Use descriptive names for variables, methods, and files to improve code clarity.
- Avoid File Locking Issues:
- Ensure that Excel and properties files are closed before and after test execution to prevent locking problems.
8.5.2. Troubleshooting Common Issues
- File Not Found Exception:
- Cause: Incorrect file path or missing file.
- Solution: Verify the file path using
System.getProperty("user.dir")
and ensure the file exists in the specified location.
- NullPointerException:
- Cause: Attempting to access a cell or row that doesn’t exist.
- Solution: Ensure that the Excel sheet has the expected number of rows and columns. Use
ExcelUtils
methods to retrieve counts dynamically.
- Number Format Exception:
- Cause: Parsing non-numeric strings to numeric types.
- Solution: Validate and sanitize input data. Remove any non-numeric characters (like $) before parsing.
- Element Not Found Exception:
- Cause: Incorrect XPath or changes in the application’s UI.
- Solution: Re-validate the XPath selectors using browser developer tools and update them as needed.
- Test Data Inconsistencies:
- Cause: Mismatch between expected and actual data.
- Solution: Ensure that the expected maturity values in Excel are accurately calculated using the correct formula.
- File Locking Issues:
- Cause: Excel or properties files are open during test execution.
- Solution: Close all instances of the files before running tests. Ensure that
ExcelUtils
properly closes file streams.
8.6. Conclusion
Implementing Data-Driven Testing enhances the scalability, reusability, and maintainability of automated test suites. By leveraging Excel for test data management and properties files for configuration, testers can efficiently execute multiple test scenarios with varying inputs without duplicating code.
Key Takeaways:
- Separation of Concerns: Distinguish between test logic and test data to simplify test case management.
- Utility Classes: Encapsulate repetitive tasks within utility classes to promote code reuse.
- Configuration Management: Utilize properties files to centralize configuration data, reducing the need for code changes.
- Robust Validation: Implement thorough validation mechanisms to ensure test accuracy and reliability.
- Best Practices: Adhere to coding best practices to enhance test suite efficiency and ease of maintenance.
Next Steps:
- Explore Advanced DDT Techniques:
- Incorporate frameworks like TestNG or JUnit for enhanced test management and reporting.
- Integrate with Continuous Integration (CI) Tools:
- Automate test executions using CI tools like Jenkins or GitHub Actions for continuous testing.
- Enhance Reporting Mechanisms:
- Implement detailed reporting using tools like ExtentReports or Allure for better visibility into test outcomes.
- Expand Utility Classes:
- Add more utility methods to handle complex Excel operations, such as formatting, conditional styling, and data validation.
- Implement Page Object Model (POM):
- Adopt the POM design pattern to further modularize test scripts and improve maintainability.
Happy Testing! 🚀