NỘI DUNG BÀI HỌC

✅ Thêm thư viện hỗ trợ xử lý Excel file trong Maven project
✅ Xây dựng class xử lý Excel file (đọc/ghi)
✅ Đọc data test từ Excel file cho test cases
✅ DataProvider trong TestNG Framework
✅ Data-driven Testing với DataProvider và Excel file

✅ Thêm thư viện hỗ trợ xử lý Excel file trong Maven project

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.19.0</version>
</dependency>
Markup


Bản cập nhật mới nhất đến ngày 06/04/2025.

✅ Xây dựng class xử lý Excel file (đọc/ghi)

Chúng ta tạo class ExcelHelpers trong package helpers như sau:

package com.anhtester.helpers;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class ExcelHelpers {

    private FileInputStream fis;
    private FileOutputStream fileOut;
    private Workbook workbook;
    private Sheet sheet;
    private Cell cell;
    private Row row;
    private String excelFilePath;
    private Map<String, Integer> columns = new HashMap<>();

    public ExcelHelpers() {
    }

    //Set Excel File
    public void setExcelFile(String excelPath, String sheetName) {
        System.out.println("Set Excel File: " + excelPath);
        System.out.println("Sheet Name: " + sheetName);

        try {
            File f = new File(excelPath);

            if (!f.exists()) {
                try {
                    System.out.println("File Excel path not found.");
                    throw new FileNotFoundException("File Excel path not found.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (sheetName.isEmpty()) {
                try {
                    System.out.println("The Sheet Name is empty.");
                    throw new FileNotFoundException("The Sheet Name is empty.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            fis = new FileInputStream(excelPath);
            workbook = WorkbookFactory.create(fis);
            sheet = workbook.getSheet(sheetName);
            //sh = wb.getSheetAt(0); //0 - index of 1st sheet
            if (sheet == null) {
                //sh = wb.createSheet(sheetName);
                try {
                    System.out.println("Sheet name not found.");
                    throw new RuntimeException("Sheet name not found.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            excelFilePath = excelPath;

            //adding all the column header names to the map 'columns'
            sheet.getRow(0).forEach(cell -> {
                columns.put(cell.getStringCellValue(), cell.getColumnIndex());
            });

        } catch (Exception e) {
            e.getMessage();
            System.out.println(e.getMessage());
        }
    }

    //This method takes the row number as a parameter and returns the data for that row.
    public Row getRowData(int rowNum) {
        row = sheet.getRow(rowNum);
        return row;
    }

    //Get Excel data from the sheet
    public Object[][] getExcelData(String excelPath, String sheetName) {
        Object[][] data = null;
        Workbook workbook = null;

        System.out.println("Set Excel file " + excelPath);
        System.out.println("Selected Sheet: " + sheetName);

        try {

            File f = new File(excelPath);

            if (!f.exists()) {
                try {
                    System.out.println("File Excel path not found.");
                    throw new FileNotFoundException("File Excel path not found.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (sheetName.isEmpty()) {
                try {
                    System.out.println("The Sheet Name is empty.");
                    throw new FileNotFoundException("The Sheet Name is empty.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            // load the file
            FileInputStream fis = new FileInputStream(excelPath);

            // load the workbook
            workbook = new XSSFWorkbook(fis);
            // load the sheet
            Sheet sheet = workbook.getSheet(sheetName);
            // load the row
            Row row = sheet.getRow(0);

            int noOfRows = sheet.getPhysicalNumberOfRows();
            int noOfCols = row.getLastCellNum();

            System.out.println("Row: " + (noOfRows - 1) + " - Column: " + noOfCols);

            Cell cell;
            data = new Object[noOfRows - 1][noOfCols];

            //FOR loop runs from 1 to drop header line (headline is 0)
            for (int i = 1; i < noOfRows; i++) {
                for (int j = 0; j < noOfCols; j++) {
                    row = sheet.getRow(i);
                    cell = row.getCell(j);

                    //This is used to determine the data type from cells in Excel and then convert it to String for ease of reading
                    switch (cell.getCellType()) {
                        case STRING:
                            data[i - 1][j] = cell.getStringCellValue();
                            break;
                        case NUMERIC:
                            data[i - 1][j] = String.valueOf(cell.getNumericCellValue());
                            break;
                        case BLANK:
                            data[i - 1][j] = "";
                            break;
                        default:
                            data[i - 1][j] = null;
                            break;
                    }
                }
            }
        } catch (Exception e) {
            e.getMessage();
            throw new RuntimeException(e);
        }
        return data;
    }

    public Object[][] getDataHashTable(String excelPath, String sheetName, int startRow, int endRow) {
        System.out.println("Excel File: " + excelPath);
        System.out.println("Sheet Name: " + sheetName);

        Object[][] data = null;

        try {

            File f = new File(excelPath);

            if (!f.exists()) {
                try {
                    System.out.println("File Excel path not found.");
                    throw new RuntimeException("File Excel path not found.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            fis = new FileInputStream(excelPath);
            workbook = new XSSFWorkbook(fis);
            sheet = workbook.getSheet(sheetName);

            int rows = getRows();
            int columns = getColumns();

            System.out.println("Row: " + rows + " - Column: " + columns);
            System.out.println("StartRow: " + startRow + " - EndRow: " + endRow);

            data = new Object[(endRow - startRow) + 1][1];
            Hashtable<String, String> table = null;
            for (int rowNums = startRow; rowNums <= endRow; rowNums++) {
                table = new Hashtable<>();
                for (int colNum = 0; colNum < columns; colNum++) {
                    table.put(getCellData(0, colNum), getCellData(rowNums, colNum));
                }
                data[rowNums - startRow][0] = table;
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }

        return data;

    }

    // Get data from specific rows
    public Object[][] getDataFromSpecificRows(String excelPath, String sheetName, int[] rowNumbers) {
        System.out.println("Excel File: " + excelPath);
        System.out.println("Sheet Name: " + sheetName);
        System.out.println("Reading data from specific rows: " + Arrays.toString(rowNumbers));

        Object[][] data = null;

        try {
            File f = new File(excelPath);

            if (!f.exists()) {
                System.out.println("File Excel path not found.");
                throw new FileNotFoundException("File Excel path not found.");
            }

            fis = new FileInputStream(excelPath);
            workbook = WorkbookFactory.create(fis);
            sheet = workbook.getSheet(sheetName);

            if (sheet == null) {
                System.out.println("Sheet name not found.");
                throw new RuntimeException("Sheet name not found.");
            }

            int columns = getColumns();
            System.out.println("Column count: " + columns);

            // Khởi tạo mảng data với kích thước bằng số lượng dòng được chỉ định
            data = new Object[rowNumbers.length][columns];

            // Đọc dữ liệu từ các dòng được chỉ định
            for (int i = 0; i < rowNumbers.length; i++) {
                int rowNum = rowNumbers[i];
                // Kiểm tra xem dòng có tồn tại không
                if (rowNum > sheet.getLastRowNum()) {
                    System.out.println("WARNING: Row " + rowNum + " does not exist in the sheet.");
                    // Gán giá trị rỗng cho dòng không tồn tại
                    for (int j = 0; j < columns; j++) {
                        data[i][j] = "";
                    }
                    continue;
                }

                for (int j = 0; j < columns; j++) {
                    data[i][j] = getCellData(rowNum, j);
                }
            }

            // Đóng workbook và FileInputStream
            workbook.close();
            fis.close();

        } catch (Exception e) {
            System.out.println("Exception in getDataFromSpecificRows: " + e.getMessage());
            e.printStackTrace();
        }

        return data;
    }

    // Get data from specific rows with hashtable
    public Object[][] getDataHashTableFromSpecificRows(String excelPath, String sheetName, int[] rowNumbers) {
        System.out.println("Excel File: " + excelPath);
        System.out.println("Sheet Name: " + sheetName);
        System.out.println("Reading data from specific rows: " + Arrays.toString(rowNumbers));

        Object[][] data = null;

        try {
            File f = new File(excelPath);

            if (!f.exists()) {
                System.out.println("File Excel path not found.");
                throw new FileNotFoundException("File Excel path not found.");
            }

            fis = new FileInputStream(excelPath);
            workbook = WorkbookFactory.create(fis);
            sheet = workbook.getSheet(sheetName);

            if (sheet == null) {
                System.out.println("Sheet name not found.");
                throw new RuntimeException("Sheet name not found.");
            }

            int columns = getColumns();
            // Khởi tạo mảng data với kích thước bằng số lượng dòng được chỉ định
            data = new Object[rowNumbers.length][1];

            // Đọc dữ liệu từ các dòng được chỉ định
            for (int i = 0; i < rowNumbers.length; i++) {
                int rowNum = rowNumbers[i];
                // Kiểm tra xem dòng có tồn tại không
                if (rowNum > sheet.getLastRowNum()) {
                    System.out.println("WARNING: Row " + rowNum + " does not exist in the sheet.");
                    data[i][0] = new Hashtable<String, String>();
                    continue;
                }

                Hashtable<String, String> table = new Hashtable<>();
                for (int j = 0; j < columns; j++) {
                    // Lấy tên cột từ dòng đầu tiên (header)
                    String columnName = getCellData(0, j);
                    // Lấy giá trị từ dòng hiện tại và cột j
                    String cellValue = getCellData(rowNum, j);
                    // Thêm vào Hashtable
                    table.put(columnName, cellValue);
                }
                data[i][0] = table;
            }

            // Đóng workbook và FileInputStream
            workbook.close();
            fis.close();

        } catch (Exception e) {
            System.out.println("Exception in getDataHashTableFromSpecificRows: " + e.getMessage());
            e.printStackTrace();
        }

        return data;
    }

    public int getRowContains(String sTestCaseName, int colNum) {
        int i;
        int rowCount = getRows();
        for (i = 0; i < rowCount; i++) {
            if (getCellData(i, colNum).equalsIgnoreCase(sTestCaseName)) {
                break;
            }
        }
        return i;
    }

    public int getRows() {
        try {
            return sheet.getLastRowNum();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw (e);
        }
    }

    public int getColumns() {
        try {
            row = sheet.getRow(0);
            return row.getLastCellNum();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw (e);
        }
    }

    // Get cell data
    public String getCellData(int rowNum, int colNum) {
        try {
            cell = sheet.getRow(rowNum).getCell(colNum);
            String CellData = null;
            switch (cell.getCellType()) {
                case STRING:
                    CellData = cell.getStringCellValue();
                    break;
                case NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        CellData = String.valueOf(cell.getDateCellValue());
                    } else {
                        CellData = String.valueOf((long) cell.getNumericCellValue());
                    }
                    break;
                case BOOLEAN:
                    CellData = Boolean.toString(cell.getBooleanCellValue());
                    break;
                case BLANK:
                    CellData = "";
                    break;
            }
            return CellData;
        } catch (Exception e) {
            return "";
        }
    }

    public String getCellData(int rowNum, String columnName) {
        return getCellData(rowNum, columns.get(columnName));
    }

    public String getCellData(String columnName, int rowNum) {
        return getCellData(rowNum, columns.get(columnName));
    }

    // Write data to excel sheet
    public void setCellData(String text, int rowNumber, int colNumber) {
        try {
            row = sheet.getRow(rowNumber);
            if (row == null) {
                row = sheet.createRow(rowNumber);
            }
            cell = row.getCell(colNumber);

            if (cell == null) {
                cell = row.createCell(colNumber);
            }
            cell.setCellValue(text);

            XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
            text = text.trim().toLowerCase();
            if (text == "pass" || text == "passed" || text == "success") {
                style.setFillForegroundColor(IndexedColors.BRIGHT_GREEN.getIndex());
            }
            if (text == "fail" || text == "failed" || text == "failure") {
                style.setFillForegroundColor(IndexedColors.RED.getIndex());
            }
            style.setFillPattern(FillPatternType.NO_FILL);
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);

            cell.setCellStyle(style);

            fileOut = new FileOutputStream(excelFilePath);
            workbook.write(fileOut);
            fileOut.flush();
            fileOut.close();
        } catch (Exception e) {
            e.getMessage();
            System.out.println(e.getMessage());
        }
    }

    public void setCellData(String text, int rowNumber, String columnName) {
        try {
            row = sheet.getRow(rowNumber);
            if (row == null) {
                row = sheet.createRow(rowNumber);
            }
            cell = row.getCell(columns.get(columnName));

            if (cell == null) {
                cell = row.createCell(columns.get(columnName));
            }
            cell.setCellValue(text);

            XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
            text = text.trim().toLowerCase();
            if (text == "pass" || text == "passed" || text == "success") {
                style.setFillForegroundColor(IndexedColors.BRIGHT_GREEN.getIndex());
            }
            if (text == "fail" || text == "failed" || text == "failure") {
                style.setFillForegroundColor(IndexedColors.RED.getIndex());
            }

            style.setFillPattern(FillPatternType.NO_FILL);
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);

            cell.setCellStyle(style);

            fileOut = new FileOutputStream(excelFilePath);
            workbook.write(fileOut);
            fileOut.flush();
            fileOut.close();

            System.out.println("Write data to excel file successfully.");

        } catch (Exception e) {
            e.getMessage();
            System.out.println(e.getMessage());
        }
    }

}
Java

 

1. setExcelFile(String excelPath, String sheetName)

  • Mục đích: Thiết lập đường dẫn và chọn sheet trong tập tin Excel cần làm việc.

  • Hoạt động:

    • Kiểm tra xem tập tin Excel và sheet đã tồn tại chưa.

    • Đọc và load nội dung của sheet vào WorkbookSheet.

    • Tạo một bản đồ (Map) các cột dựa vào hàng đầu tiên (header) của sheet, giúp truy cập dữ liệu dễ dàng hơn bằng tên cột.


2. getRowData(int rowNum)

  • Mục đích: Lấy dữ liệu của một hàng cụ thể.

  • Hoạt động: Trả về đối tượng Row tại vị trí được truyền vào (rowNum).


3. getExcelData(String excelPath, String sheetName)

  • Mục đích: Trả về toàn bộ dữ liệu trong sheet dưới dạng mảng 2 chiều (Object[][]).

  • Hoạt động:

    • Load workbook và sheet.

    • Đếm số dòng và cột dữ liệu.

    • Duyệt từng ô để lấy dữ liệu, chuyển đổi kiểu dữ liệu sang String hoặc các kiểu tương ứng, rồi đưa vào mảng 2 chiều.


4. getDataHashTable(String excelPath, String sheetName, int startRow, int endRow)

  • Mục đích: Lấy dữ liệu từ một phạm vi các dòng cụ thể và trả về dưới dạng mảng 2 chiều chứa Hashtable (cặp key-value).

  • Hoạt động:

    • Duyệt từ startRow đến endRow, mỗi dòng dữ liệu được lưu vào một Hashtable.

    • Key trong Hashtable là tên cột, giá trị là dữ liệu từ từng ô tương ứng trong hàng đó.


5. getRowContains(String sTestCaseName, int colNum)

  • Mục đích: Tìm vị trí dòng đầu tiên có chứa giá trị xác định trong một cột nhất định.

  • Hoạt động:

    • Duyệt tất cả các dòng, kiểm tra giá trị của ô tại cột (colNum) so sánh với chuỗi cần tìm.

    • Trả về vị trí của dòng chứa chuỗi đó.


6. getRows()

  • Mục đích: Trả về tổng số dòng hiện có trong sheet.

  • Hoạt động: Gọi phương thức getLastRowNum() từ đối tượng Sheet.


7. getColumns()

  • Mục đích: Trả về tổng số cột hiện có trong hàng đầu tiên của sheet.

  • Hoạt động: Dựa vào hàng đầu tiên (getRow(0)) và gọi getLastCellNum() để lấy số cột.


8. getCellData(int rowNum, int colNum)

  • Mục đích: Lấy dữ liệu từ ô cụ thể theo vị trí dòng và cột.

  • Hoạt động:

    • Xác định kiểu dữ liệu của ô (STRING, NUMERIC, BOOLEAN, DATE, BLANK).

    • Chuyển đổi sang kiểu chuỗi và trả về giá trị.


9. getCellData(int rowNum, String columnName) & getCellData(String columnName, int rowNum)

  • Mục đích: Lấy dữ liệu từ ô cụ thể theo tên cột và số dòng, tiện lợi khi thao tác với bảng dữ liệu có header.

  • Hoạt động:

    • Xác định số cột từ tên cột bằng Map columns.

    • Gọi lại hàm getCellData(int rowNum, int colNum) để lấy giá trị.


10. setCellData(String text, int rowNumber, int colNumber)

  • Mục đích: Ghi dữ liệu vào một ô cụ thể trong Excel, định dạng ô tùy theo nội dung.

  • Hoạt động:

    • Tạo dòng và ô mới nếu chưa tồn tại.

    • Ghi dữ liệu vào ô.

    • Định dạng ô dựa theo nội dung (pass, fail) với màu sắc tương ứng.

    • Lưu lại nội dung vào file Excel.


11. setCellData(String text, int rowNumber, String columnName)

  • Mục đích: Ghi dữ liệu vào ô Excel dựa trên số dòng và tên cột.

  • Hoạt động:

    • Chuyển tên cột sang chỉ số cột nhờ columns.

    • Thực hiện tương tự hàm setCellData theo số dòng và cột.



✅ Đọc data test từ Excel file cho test cases

Tạo file data excel lưu vào src/test/resources/test_data/data.xlsx




🚩 1. Đặt tên file và sheet rõ ràng, dễ hiểu

  • Đặt tên file Excel và tên sheet ngắn gọn, rõ ràng, phản ánh đúng mục đích dữ liệu.

  • Ví dụ:

    • Tên file: LoginData.xlsx, data.xlsx, product.xlsx,...

    • Tên sheet: UserCredentials, Login, Product, Table,...

 

🚩 2. Sử dụng đúng định dạng file

  • Apache POI: Hỗ trợ tốt nhất cho định dạng .xlsx.

  • Luôn ưu tiên file Excel dạng .xlsx.

 

🚩 3. Đặt header (tiêu đề cột) rõ ràng

  • Dòng đầu tiên luôn là tiêu đề cột (Header).

  • Tiêu đề cột phải dễ đọc, ngắn gọn, tránh ký tự đặc biệt. Nên viết in hoa tất cả.

 

🚩 4. Tránh các ô merge (gộp ô)

  • Không dùng Merge Cells vì Apache POI và Selenium sẽ khó đọc hoặc phát sinh lỗi.

  • Mỗi ô chỉ nên chứa một giá trị duy nhất.

 

🚩 5. Định dạng dữ liệu đúng cách

  • Kiểu chuỗi (text):
    Định dạng cell là text, tránh các khoảng trắng thừa.

  • Kiểu số (numeric):
    Định dạng rõ ràng, không chèn ký tự thừa như dấu phẩy, khoảng trắng.

  • Ngày tháng:
    Dùng định dạng thống nhất:
    Ví dụ: yyyy-MM-dd

 

🚩 6. Tránh các ký tự đặc biệt trong dữ liệu

  • Tránh sử dụng ký tự đặc biệt không cần thiết như:

    ", ', `, ;, [, ], (, ), #
    Java
  • Nếu bắt buộc, cần xử lý escape phù hợp khi đọc dữ liệu.

🚩 7. Không để dòng hoặc cột trống ở giữa dữ liệu

  • Đảm bảo dữ liệu luôn liền mạch, không có khoảng trống dòng/cột ngẫu nhiên.
  • Nên delete vài dòng dư phía bên dưới và vài cột dư phía bên phải cho chắc chắn.

🚩 8. Đóng file Excel trước khi chạy test

  • Luôn đóng file Excel trước khi chạy script test để tránh lỗi do file đang mở và bị lock.


🚩 9. Sắp xếp dữ liệu hợp lý

  • Các test case chính xác và ổn định hơn khi dữ liệu được tổ chức logic.

  • Đưa các dữ liệu liên quan gần nhau, nhóm theo từng test scenario.


🚩 10. Giới hạn dữ liệu hợp lý

  • Không đưa quá nhiều dữ liệu không cần thiết vào một sheet.

  • Dữ liệu quá lớn sẽ làm chậm tốc độ đọc ghi và chạy test.


🚩 11. Kiểm tra encoding (mã hóa ký tự)

  • Luôn đảm bảo file Excel lưu với định dạng chuẩn UTF-8 để tránh lỗi đọc ghi ký tự đặc biệt.


📌 Ví dụ mẫu về cấu trúc Excel chuẩn trong một sheet

USERNAME PASSWORD EXPECTED_RESULT
admin admin123 Success
admin pass456 Fail
admin123 admin Success

 


🔆 Đọc data từ file Excel

package com.anhtester.Bai23_Excel_File;

import com.anhtester.helpers.ExcelHelpers;
import org.testng.annotations.Test;

public class DemoExcelFile {

    @Test
    public void testReadExcelFile() {
        String filePath = "src/test/resources/test_data/data.xlsx";
        ExcelHelpers excelHelpers = new ExcelHelpers();
        excelHelpers.setExcelFile(filePath, "Login");

        System.out.println("USERNAME: " + excelHelpers.getCellData(1, "USERNAME"));
        System.out.println("PASSWORD: " + excelHelpers.getCellData(1, "PASSWORD"));

        System.out.println("USERNAME: " + excelHelpers.getCellData(2, "USERNAME"));
        System.out.println("PASSWORD: " + excelHelpers.getCellData(2, "PASSWORD"));

    }

}
Java

 

🔆 Đọc data từ file Excel cho test cases

package com.anhtester.Bai23_Excel_File.testcases;

import com.anhtester.Bai23_Excel_File.pages.LoginPage;
import com.anhtester.common.BaseTest_Json_Device;
import com.anhtester.helpers.ExcelHelpers;
import org.testng.annotations.Test;

public class LoginTest extends BaseTest_Json_Device {

    private LoginPage loginPage;

    @Test
    public void testLoginSuccess() {
        loginPage = new LoginPage();

        ExcelHelpers excelHelpers = new ExcelHelpers();
        String filePath = "src/test/resources/test_data/data.xlsx";
        excelHelpers.setExcelFile(filePath, "Login");
        String username = excelHelpers.getCellData(1, "USERNAME");
        String password = excelHelpers.getCellData(1, "PASSWORD");
        System.out.println("USERNAME: " + username);
        System.out.println("PASSWORD: " + password);

        loginPage.login(username, password);
        loginPage.verifyLoginSuccess();
    }

    @Test
    public void testLoginFailWithUsernameInvalid() {
        loginPage = new LoginPage();

        ExcelHelpers excelHelpers = new ExcelHelpers();
        String filePath = "src/test/resources/test_data/data.xlsx";
        excelHelpers.setExcelFile(filePath, "Login");
        String username = excelHelpers.getCellData(2, "USERNAME");
        String password = excelHelpers.getCellData(2, "PASSWORD");
        System.out.println("USERNAME: " + username);
        System.out.println("PASSWORD: " + password);

        loginPage.login(username, password);

        loginPage.verifyLoginFail();
    }
}
Java

 

🔆 Ghi data vào file Excel

package com.anhtester.Bai23_Excel_File;

import com.anhtester.helpers.ExcelHelpers;
import org.testng.annotations.Test;

public class DemoExcelFile {

    @Test
    public void testReadExcelFile() {
        String filePath = "src/test/resources/test_data/data.xlsx";
        ExcelHelpers excelHelpers = new ExcelHelpers();
        excelHelpers.setExcelFile(filePath, "Login");

        System.out.println("USERNAME: " + excelHelpers.getCellData(1, "USERNAME"));
        System.out.println("PASSWORD: " + excelHelpers.getCellData(1, "PASSWORD"));

        System.out.println("USERNAME: " + excelHelpers.getCellData(2, "USERNAME"));
        System.out.println("PASSWORD: " + excelHelpers.getCellData(2, "PASSWORD"));

    }

    @Test
    public void testWriteExcelFile() {
        String filePath = "src/test/resources/test_data/data.xlsx";
        ExcelHelpers excelHelpers = new ExcelHelpers();
        excelHelpers.setExcelFile(filePath, "Login");
        
        excelHelpers.setCellData("Passed", 1, "EXPECTED_RESULT");
        excelHelpers.setCellData("Failed", 2, "EXPECTED_RESULT");
    }

}
Java

📌 Lưu ý: khi set data vào file thì cần đóng file Excel trước khi ghi, nguyên tắc trong Window là như thế, nếu không nó sẽ bị chiếm tiến trình không thể ghi giá trị vào được.

⭐️ Thay các đường dẫn file Excel thành biến toàn cục đặt trong Properties file và ConfigData class





 

✅ DataProvider trong TestNG Framework

 

🟢 DataProvider trong TestNG là gì?

  • DataProvider là một tính năng rất mạnh của TestNG cho phép thực hiện Data-Driven Testing (kiểm thử dựa trên dữ liệu).

  • Nó cung cấp dữ liệu đầu vào cho một test method, cho phép test method được chạy nhiều lần với các dữ liệu đầu vào khác nhau.


📌 Tại sao nên dùng DataProvider?

  • Thay vì phải viết nhiều test case giống nhau chỉ khác dữ liệu, em chỉ cần viết một test method duy nhất, rồi cung cấp các bộ dữ liệu khác nhau từ DataProvider.

  • Tăng khả năng tái sử dụng mã nguồn.

  • Dễ dàng quản lý và mở rộng dữ liệu test.


📌 Cách khai báo và sử dụng DataProvider trong TestNG:


✔️ Bước 1: Tạo DataProvider

@DataProvider(name = "loginData")
public Object[][] loginData() {
    return new Object[][]{
        {"user1", "pass1"},
        {"user2", "pass2"},
        {"user3", "pass3"}
    };
}
Java
  • DataProvider trả về dữ liệu dưới dạng mảng 2 chiều (Object[][]).

  • Mỗi dòng trong mảng là một bộ dữ liệu test riêng biệt.

  • Các bộ data cách nhau bởi dấu phẩy và các bộ data phải có cùng tham số và kiểu dữ liệu.

Theo ví dụ trên là 3 bộ data khác nhau. Mỗi bộ data có 2 tham số.

✔️ Bước 2: Liên kết DataProvider với Test method

@Test(dataProvider = "loginData")
public void loginTest(String username, String password) {
    System.out.println("Username: " + username);
    System.out.println("Password: " + password);
    
    // Thực hiện thao tác test login ở đây...
}
Java
  • Tham số truyền vào test method chính là giá trị của từng bộ dữ liệu mà DataProvider cung cấp.

  • Chú ý số lượng tham số phải tương ứng, kiểu dữ liệu tương ứng trong DataProvider. (tên tham số tuỳ ý)


Có 3 bộ data nên kết quả chạy 3 lần, mỗi lần bộ data khác nhau.


📌 Trường hợp sử dụng DataProvider từ một class khác:

Giờ chúng ta xây dựng một class chứa DataProvider riêng biệt, ví dụ DataProviderFactory:

package com.anhtester.dataproviders;

import org.testng.annotations.DataProvider;

public class DataProviderFactory {

    @DataProvider(name = "loginSuccess")
    public Object[][] userDataLoginSuccess() {
        return new Object[][]{{"admin", "admin123"}, {"test", "test123"}};
    }

}
Java


Để sử dụng trong test class khác, chúng ta khai báo như sau:

@Test(dataProvider = "loginSuccess", dataProviderClass = DataProviderFactory.class)
public void testLogin(String username, String password) {
    System.out.println("Login with: " + username + " - " + password);
}
Java





✅ Data-driven Testing với DataProvider và Excel file

 

🔆 Đọc hết data trong một Sheet từ Excel

Chúng ta gọi hàm getExcelData() để xử lý trường hợp đọc hết data trong một Sheet, sau đó truyền vào DataProvider tại class DataProviderFactory.

@DataProvider(name = "login_from_excel")
public Object[][] login_from_excel() {
    ExcelHelpers excelHelpers = new ExcelHelpers();
    return excelHelpers.getExcelData(
        ConfigData.EXCEL_DATA_FILE_PATH,
        "Login"
    );
}
Java


Tiếp theo chúng ta khai báo test cases để tiếp nhận data từ DataProvider tên "login_from_excel"

@Test(dataProvider = "login_from_excel", dataProviderClass = DataProviderFactory.class)
public void testLoginFromExcel(String username, String password) {
    System.out.println("Login with: " + username + " - " + password);
}
Java

 

🔆 Đọc data theo vị trí dòng chỉ định trong một Sheet từ Excel

Chúng ta gọi hàm getDataHashTable() để xử lý trường hợp đọc data theo vị trí dòng bắt đầu và dòng kết thúc được chỉ định trong một Sheet, sau đó cũng truyền vào DataProvider tại class DataProviderFactory.

@DataProvider(name = "login_from_excel_hashtable")
public Object[][] login_from_excel_hashtable() {
    ExcelHelpers excelHelpers = new ExcelHelpers();
    return excelHelpers.getDataHashTable(
        ConfigData.EXCEL_DATA_FILE_PATH,
        "Login",
        2,
        3
    );
}
Java


Tiếp theo chúng ta khai báo test cases để tiếp nhận data từ DataProvider tên "login_from_excel_hashtable". Lúc này hơi khác với trước giờ theo kiểu truyền tham số. Cách này buộc truyền tham số là đối tượng HashTable<String, String>.

@Test(dataProvider = "login_from_excel_hashtable", dataProviderClass = DataProviderFactory.class)
public void testLoginFromExcelHashtable(Hashtable<String, String> data) {
    System.out.println("Login with: " + data.get("USERNAME") + " - " + data.get("PASSWORD"));
}
Java




🔆 Đọc data theo từng vị trí dòng cụ thể trong một Sheet từ Excel

Chúng ta gọi hàm getDataFromSpecificRows() hoặc getDataHashTableFromSpecificRows() để xử lý trường hợp đọc data theo từng vị trí cụ thể được chỉ định trong một Sheet, sau đó cũng truyền vào DataProvider tại class DataProviderFactory.

@DataProvider(name = "login_specific_rows")
public Object[][] login_specific_rows() {
    ExcelHelpers excelHelpers = new ExcelHelpers();
    // Đọc dữ liệu từ các dòng 1, 3
    int[] specificRows = new int[] {
        1,
        3
    };
    return excelHelpers.getDataFromSpecificRows(
        ConfigData.EXCEL_DATA_FILE_PATH,
        "Login",
        specificRows
    );
}

@DataProvider(name = "login_specific_rows_hashtable")
public Object[][] login_specific_rows_hashtable() {
    ExcelHelpers excelHelpers = new ExcelHelpers();
    // Đọc dữ liệu từ các dòng 1, 3
    int[] specificRows = new int[] {
        1,
        3
    };
    return excelHelpers.getDataHashTableFromSpecificRows(
        ConfigData.EXCEL_DATA_FILE_PATH,
        "Login",
        specificRows
    );
}
Java


Gọi sử dụng trong test cases class

// Sử dụng DataProvider với các dòng cụ thể cố định (1, 3)
@Test(dataProvider = "login_specific_rows", dataProviderClass = DataProviderFactory.class)
public void testLoginWithSpecificRows(String username, String password) {
    System.out.println("Username: " + username);
    System.out.println("Password: " + password);
}

// Sử dụng DataProvider với các dòng cụ thể dạng Hashtable
@Test(dataProvider = "login_specific_rows_hashtable", dataProviderClass = DataProviderFactory.class)
public void testLoginWithSpecificRowsHashtable(Hashtable<String, String> data) {
    String username = data.get("USERNAME");
    String password = data.get("PASSWORD");

    System.out.println("Username: " + username);
    System.out.println("Password: " + password);
}
Java

 

🔆 Truyền tham số từ suite XML file vào DataProvider

Chúng ta có thể xây dựng thêm các hàm tuỳ biến có thể truyền tham số từ Class hoặc XML file vào DataProvider để tiện get data linh hoạt hơn.

Bổ sung 2 hàm sau vào DataProviderFactory để có thể truyền tham số từ XML file:

// Thêm các phương thức này vào lớp DataProviderFactory

/**
 * DataProvider động cho phép truyền tham số là các dòng cần đọc
 * 
 * @param rowIndices Chuỗi chứa các chỉ số dòng, phân cách bởi dấu phẩy, ví dụ: "1,3,5"
 * @return Dữ liệu từ các dòng được chỉ định
 */
@DataProvider(name = "dynamic_rows")
public Object[][] dynamic_rows(ITestContext context) {
    // Lấy tham số từ test context hoặc suite XML
    String rowIndicesStr = context.getCurrentXmlTest().getParameter("rowIndices");
    if (rowIndicesStr == null || rowIndicesStr.isEmpty()) {
        // Mặc định đọc các dòng 1, 2, 3 nếu không có tham số nào được truyền
        rowIndicesStr = "1,2,3";
    }
    
    // Chuyển đổi chuỗi thành mảng các số nguyên
    int[] rowIndices = Arrays.stream(rowIndicesStr.split(","))
                            .map(String::trim)
                            .mapToInt(Integer::parseInt)
                            .toArray();
    
    ExcelHelpers excelHelpers = new ExcelHelpers();
    return excelHelpers.getDataFromSpecificRows(
            ConfigData.EXCEL_DATA_FILE_PATH,
            "Login",
            rowIndices
    );
}

/**
 * DataProvider động trả về dữ liệu dạng Hashtable
 * 
 * @param rowIndices Chuỗi chứa các chỉ số dòng, phân cách bởi dấu phẩy, ví dụ: "1,3,5"
 * @return Dữ liệu dạng Hashtable từ các dòng được chỉ định
 */
@DataProvider(name = "dynamic_rows_hashtable")
public Object[][] dynamic_rows_hashtable(ITestContext context) {
    // Lấy tham số từ test context hoặc suite XML
    String rowIndicesStr = context.getCurrentXmlTest().getParameter("rowIndices");
    if (rowIndicesStr == null || rowIndicesStr.isEmpty()) {
        // Mặc định đọc các dòng 1, 2, 3 nếu không có tham số nào được truyền
        rowIndicesStr = "1,2,3";
    }
    
    // Chuyển đổi chuỗi thành mảng các số nguyên
    int[] rowIndices = Arrays.stream(rowIndicesStr.split(","))
                            .map(String::trim)
                            .mapToInt(Integer::parseInt)
                            .toArray();
    
    ExcelHelpers excelHelpers = new ExcelHelpers();
    return excelHelpers.getDataHashTableFromSpecificRows(
            ConfigData.EXCEL_DATA_FILE_PATH,
            "Login",
            rowIndices
    );
}
Java


Gọi DataProvider sang test cases

// Sử dụng DataProvider động với tham số từ testng.xml
@Test(dataProvider = "dynamic_rows", dataProviderClass = DataProviderFactory.class)
public void testLoginWithDynamicRows(String username, String password) {
    System.out.println("Username: " + username);
    System.out.println("Password: " + password);

    // Thêm code để thực hiện đăng nhập và kiểm tra kết quả ở đây
}

// Sử dụng DataProvider động dạng Hashtable với tham số từ testng.xml
@Test(dataProvider = "dynamic_rows_hashtable", dataProviderClass = DataProviderFactory.class)
public void testLoginWithDynamicRowsHashtable(Hashtable < String, String > data) {
    String username = data.get("username");
    String password = data.get("password");

    System.out.println("Username: " + username);
    System.out.println("Password: " + password);

    // Thêm code để thực hiện đăng nhập và kiểm tra kết quả ở đây
}
Java


Tạo file suite XML truyền tham số là các dòng Excel cụ thể, phân cách bởi dấu phẩy.

Nếu không nhận được tham số từ XML thì hàm trong DataProvider sẽ lấy giá trị default được khai báo trong hàm.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Test Suite">
    <test name="Login Test with Specific Rows">
        <!-- Định nghĩa các dòng bạn muốn đọc dữ liệu từ Excel (1, 3) -->
        <parameter name="rowIndices" value="1,3"/>
        <classes>
            <class name="com.anhtester.Bai23_Excel_File.DemoDataProvider">
                <methods>
                    <include name="testLoginWithDynamicRows"/>
                    <include name="testLoginWithDynamicRowsHashtable"/>
                </methods>
            </class>
        </classes>
    </test>

    <!-- Bạn có thể định nghĩa test khác với các dòng khác -->
    <test name="Login Test with Different Rows">
        <parameter name="rowIndices" value="2,3"/>
        <classes>
            <class name="com.anhtester.Bai23_Excel_File.DemoDataProvider">
                <methods>
                    <include name="testLoginWithDynamicRows"/>
                    <include name="testLoginWithDynamicRowsHashtable"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>
Markup

Teacher

Teacher

Anh Tester

Software Quality Engineer

Đường dẫu khó chân vẫn cần bước đi
Đời dẫu khổ tâm vẫn cần nghĩ thấu

Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ khóa học lên trang

Bạn có thể đăng khóa học của chính bạn lên trang Anh Tester để kiếm tiền

Danh sách bài học

2017年
12月
Clear Today
 :  : 
Clear Okey
00 01 02 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
00 05 10 15 20 25 30 35 40 45 50 55
00 05 10 15 20 25 30 35 40 45 50 55