Selenium 框架:数据、关键词和混合驱动

⚡ 智能摘要

Selenium 框架:数据驱动、关键字驱动和混合驱动方法定义了测试人员如何组织自动化代码、分离测试数据以及重用逻辑。本文将解释每种框架类型、其架构、优势,以及如何通过实际案例逐步实现它们。 Selenium WebDriver 代码示例。

  • ✅ 核心定义: A Selenium 框架是一种结构化的代码架构,可以提高自动化测试脚本的重用性、可移植性和可维护性。
  • 📊 数据驱动实施: 使用 Excel、CSV 或 XML 将测试数据与逻辑数据分开,并通过 Apache POI 读取输入(XLS 使用 HSSF,XLSX 使用 XSSF)。
  • ???? 关键词驱动设计: 通过关键字表和对象库驱动 UI 操作,以便手动测试人员无需编写代码即可构建测试用例。 Java 码。
  • ⚙️ 混合优化: 结合 TestNG 数据提供商通过关键字执行来获得灵活性、可扩展性和更低的脚本维护开销。
  • 🧩 对象库的优势: 将定位器集中在属性文件中,这样元素更改只需要在所有测试用例中更新一个位置即可。

Selenium 骨架

什么是 Selenium 框架?

此 Selenium 自动化框架 是一种结构化的代码架构,它使测试维护变得简单、可扩展且高效。如果没有框架,测试人员通常会将代码和数据放在同一位置,这既不方便重用也不易于阅读。采用框架可以带来显著的益处,例如更高的代码重用性、更好的可移植性、更低的脚本维护成本、更高的可读性以及更清晰地分离测试逻辑和输入数据之间的职责。

为什么使用 Selenium 自动化框架?

一个精心设计的 Selenium 该框架解决了测试自动化中三个长期存在的问题:代码重复、定位器脆弱以及测试数据难以管理。通过强制执行清晰的结构,团队可以将测试套件从几个脚本扩展到数百个脚本,而不会失去控制。

  • 可维护性: 集中式定位器和辅助方法意味着只需一次更改即可更新使用该元素的每个测试。
  • 可重用性: 登录、导航或表单输入等常用操作只需编写一次,即可在多个测试用例中调用。
  • 可扩展性: 添加新的测试用例变成了数据更新而不是编码任务,这使得非开发人员也能贡献场景。
  • 报告与协作: 标准化的结构使得与报告工具、CI/CD 管道和版本控制集成变得更加容易。

有哪些 Selenium 骨架

主要有以下三个 框架类型 建立在 Selenium 使用 WebDriver 实现手动测试用例的自动化。每种风格都旨在平衡开发人员的工作量、测试人员的参与度和数据灵活性。

  • 数据驱动框架
  • 关键字驱动框架
  • 混合驱动框架

有哪些 Selenium 骨架

接下来的章节将详细解释每个框架,从最简单的数据驱动方法开始,逐步过渡到最灵活的混合模型。

数据驱动框架 Selenium

数据驱动框架 Selenium 是一种将测试数据集与测试用例逻辑分离的方法。数据解耦后,您可以在不修改测试代码的情况下修改特定功能的输入。它通常用于从外部来源(例如……)获取测试用例和测试套件。 Excel.csv、.xml 或数据库表。

数据驱动框架 Selenium

Apache 提供了著名的 POI 库来读取或写入 Excel 文件。该库可以处理这两种情况。 XLS 和 XLSX 格式。 的 高速SF 该实现读取旧版 XLS 文件,而 跨系统安全框架 该实现可处理现代 XLSX 文件。

我们已经在之前的课程中介绍过数据驱动测试了。 先前的教程.

关键字驱动框架 Selenium

关键字驱动框架 Selenium 这是一种通过将常用功能和指令的关键字分离来加速自动化的方法。所有操作和指令都写在外部文件中,通常是 Excel 表格。测试人员无需修改文件即可指定要验证的功能。 Java 这种代码风格非常适合业务分析师或手动 QA 贡献测试定义的团队。

完整的框架如下所示:

关键字驱动框架 Selenium

如您所见,这是一个五步框架。让我们逐步详细地研究一下。

步骤1)

  • 驱动程序脚本 Execute.java 调用 ReadGuru99ExcelFile.java。
  • 了解 Guru99ExcelFile.java 包含从 Excel 读取数据的 POI 代码。

步骤2)

  • 了解 Guru99ExcelFile.java 从 TestCase.xlsx 读取数据。
  • 表格如下所示:

关键词驱动框架 Excel 表格 Selenium

  • 该框架根据 Excel 文件中编写的关键字,在用户界面上执行相应的操作。
  • 例如,要点击名为“登录”的按钮,Excel 表格会存储关键字“Click”。为了在页面上的众多按钮中识别出“登录”按钮,Excel 表格中的相应行会将对象名称定义为 loginButton,对象类型定义为 name(参见图中高亮显示的行)。对象类型也可以是 XPath、CSS、class 或任何其他定位策略。

步骤3) 了解 Guru99ExcelFile.java 将解析后的数据传递回驱动程序脚本 Execute.java。

步骤4)

  • 对于所有 UI Web 元素,您需要维护一个对象存储库,其中存储元素定位器,例如 XPath、名称、CSS 或类名。

关键字驱动框架中的对象存储库

  • Execute.java(驱动脚本)读取整个对象库并将其存储在一个变量中。
  • 辅助类 ReadObject 公开了一个 getObjectRepository 方法,该方法在运行时加载存储库。

关键字驱动框架的 ReadObject 辅助类

注意: 你可能想知道为什么需要对象库。答案是为了便于维护。如果一个名为 btnlogin 的按钮在 10 个测试用例中使用,而开发人员在提交时将其重命名,那么你通常需要编辑 10 个文件。而使用对象库,你只需在一个地方更改定位器即可。

步骤5)

  • 驱动程序将数据从 Excel 和对象库传递到用户界面。Operation class。
  • UIOperation 包含将每个关键字(例如 CLICK 和 SETTEXT)映射到具体 WebDriver 操作的函数。
  • UIOperation 是一个 Java 包含与网页元素交互的实际实现的类。

UIOpera关键字驱动框架中的 tion 类

完整的项目结构如下:

关键词驱动框架的完整项目结构

让我们来看一个实际例子:

测试场景: 我们正在执行 2 个测试用例。

对象.属性

url=https://demo.guru99.com/V4/
username=uid
password=password
title=barone
loginButton=btnLogin
resetButton=btnReset

了解 Guru99ExcelFile.java

package excelExportAndFileIO;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ReadGuru99ExcelFile {
    public Sheet readExcel(String filePath, String fileName, String sheetName) throws IOException {
        // Create a File object to open the xlsx file
        File file = new File(filePath + "\\" + fileName);
        // Create a FileInputStream to read the Excel file
        FileInputStream inputStream = new FileInputStream(file);
        Workbook guru99Workbook = null;
        // Detect the file extension
        String fileExtensionName = fileName.substring(fileName.indexOf("."));
        if (fileExtensionName.equals(".xlsx")) {
            guru99Workbook = new XSSFWorkbook(inputStream);
        } else if (fileExtensionName.equals(".xls")) {
            guru99Workbook = new HSSFWorkbook(inputStream);
        }
        // Read the sheet inside the workbook by its name
        Sheet guru99Sheet = guru99Workbook.getSheet(sheetName);
        return guru99Sheet;
    }
}

读取对象.java

package operation;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ReadObject {
    Properties p = new Properties();

    public Properties getObjectRepository() throws IOException {
        // Read the object repository file
        InputStream stream = new FileInputStream(new File(System.getProperty("user.dir") + "\\src\\objects\\object.properties"));
        // Load all objects
        p.load(stream);
        return p;
    }
}

UIOpera函数

package operation;
import java.util.Properties;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class UIOperation {
    WebDriver driver;

    public UIOperation(WebDriver driver) {
        this.driver = driver;
    }

    public void perform(Properties p, String operation, String objectName, String objectType, String value) throws Exception {
        System.out.println("");
        switch (operation.toUpperCase()) {
            case "CLICK":
                driver.findElement(this.getObject(p, objectName, objectType)).click();
                break;
            case "SETTEXT":
                driver.findElement(this.getObject(p, objectName, objectType)).sendKeys(value);
                break;
            case "GOTOURL":
                driver.get(p.getProperty(value));
                break;
            case "GETTEXT":
                driver.findElement(this.getObject(p, objectName, objectType)).getText();
                break;
            default:
                break;
        }
    }

    private By getObject(Properties p, String objectName, String objectType) throws Exception {
        if (objectType.equalsIgnoreCase("XPATH")) {
            return By.xpath(p.getProperty(objectName));
        } else if (objectType.equalsIgnoreCase("CLASSNAME")) {
            return By.className(p.getProperty(objectName));
        } else if (objectType.equalsIgnoreCase("NAME")) {
            return By.name(p.getProperty(objectName));
        } else if (objectType.equalsIgnoreCase("CSS")) {
            return By.cssSelector(p.getProperty(objectName));
        } else if (objectType.equalsIgnoreCase("LINK")) {
            return By.linkText(p.getProperty(objectName));
        } else if (objectType.equalsIgnoreCase("PARTIALLINK")) {
            return By.partialLinkText(p.getProperty(objectName));
        } else {
            throw new Exception("Wrong object type");
        }
    }
}

执行测试.java

package testCases;
import java.util.Properties;
import operation.ReadObject;
import operation.UIOperation;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;
import excelExportAndFileIO.ReadGuru99ExcelFile;

public class ExecuteTest {
    @Test
    public void testLogin() throws Exception {
        WebDriver webdriver = new FirefoxDriver();
        ReadGuru99ExcelFile file = new ReadGuru99ExcelFile();
        ReadObject object = new ReadObject();
        Properties allObjects = object.getObjectRepository();
        UIOperation operation = new UIOperation(webdriver);
        // Read keyword sheet
        Sheet guru99Sheet = file.readExcel(System.getProperty("user.dir") + "\\", "TestCase.xlsx", "KeywordFramework");
        // Find the number of rows in the Excel file
        int rowCount = guru99Sheet.getLastRowNum() - guru99Sheet.getFirstRowNum();
        for (int i = 1; i < rowCount + 1; i++) {
            Row row = guru99Sheet.getRow(i);
            if (row.getCell(0).toString().length() == 0) {
                System.out.println(row.getCell(1).toString() + "----" + row.getCell(2).toString() + "----" +
                        row.getCell(3).toString() + "----" + row.getCell(4).toString());
                operation.perform(allObjects, row.getCell(1).toString(), row.getCell(2).toString(),
                        row.getCell(3).toString(), row.getCell(4).toString());
            } else {
                System.out.println("New Testcase->" + row.getCell(0).toString() + " Started");
            }
        }
    }
}

执行后,输出结果如下:

关键词驱动框架执行输出

下载 Selenium 本教程中演示的项目文件

混合驱动框架

混合驱动框架 in Selenium 它融合了关键字驱动和数据驱动框架的优势。这是一个易于使用的模型,允许手动测试人员通过编辑关键字、测试数据和对象库来创建测试用例,而无需编写任何框架代码。

在这里,Excel 文件保存了每个步骤的关键字,并且 TestNG“ 数据提供者 提供测试数据。这种拆分方式允许您独立地调整动作词汇和输入变化。

混合驱动框架架构

对于我们的混合框架,关键字驱动的结构没有任何变化:我们只需将 ExecuteTest.java 替换为 HybridExecuteTest.java。

混合驱动框架组件替换

此 HybridExecuteTest 文件包含完整的关键字驱动逻辑,并结合了 TestNG的数据提供机制。

混合框架的完整图示如下所示:

混合驱动框架完整表示

混合执行测试.java

package testCases;
import java.io.IOException;
import java.util.Properties;
import operation.ReadObject;
import operation.UIOperation;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import excelExportAndFileIO.ReadGuru99ExcelFile;

public class HybridExecuteTest {
    WebDriver webdriver = null;

    @Test(dataProvider = "hybridData")
    public void testLogin(String testcaseName, String keyword, String objectName, String objectType, String value) throws Exception {
        if (testcaseName != null && testcaseName.length() != 0) {
            webdriver = new FirefoxDriver();
        }
        ReadObject object = new ReadObject();
        Properties allObjects = object.getObjectRepository();
        UIOperation operation = new UIOperation(webdriver);
        operation.perform(allObjects, keyword, objectName, objectType, value);
    }

    @DataProvider(name = "hybridData")
    public Object[][] getDataFromDataprovider() throws IOException {
        Object[][] object = null;
        ReadGuru99ExcelFile file = new ReadGuru99ExcelFile();
        Sheet guru99Sheet = file.readExcel(System.getProperty("user.dir") + "\\", "TestCase.xlsx", "KeywordFramework");
        int rowCount = guru99Sheet.getLastRowNum() - guru99Sheet.getFirstRowNum();
        object = new Object[rowCount][5];
        for (int i = 0; i < rowCount; i++) {
            Row row = guru99Sheet.getRow(i + 1);
            for (int j = 0; j < row.getLastCellNum(); j++) {
                object[i][j] = row.getCell(j).toString();
            }
        }
        System.out.println("");
        return object;
    }
}

下载 Selenium 本教程中演示的项目文件

常见问题

当手动测试人员需要构建无需编码的测试用例时,请选择关键字驱动模式。当同一脚本必须针对多种输入变体运行时,请选择数据驱动模式。当您既需要数据灵活性又需要关键字级测试编写功能时,请使用混合模式。

Apache POI 读取和写入用作数据源的 Excel 文件。HSSF 处理传统的 .xls 文件,而 XSSF 处理现代的 .xlsx 文件。它们协同工作,使您的测试脚本能够从电子表格中提取动态输入,而无需硬编码数据。

对象库集中管理元素定位器,例如 XPath、CSS 或名称。如果开发人员重命名 UI 控件,只需更新一个条目,而无需更新所有测试用例,这大大缩短了维护时间并降低了脚本出错的风险。

人工智能改善 Selenium 通过自愈定位器、智能测试优先级排序和可视化验证等框架,人工智能引擎能够检测定位器漂移、推荐稳定的选择器并分析故障模式,从而确保混合测试套件在被测应用程序不断演进的过程中始终保持可靠性。

是的。现代人工智能助手会分析被测应用程序,并提供关键字库、示例输入和边界情况建议。测试人员会审查并完善这些建议,这既能加快框架设置速度,又能保持……ping 人工对关键验证逻辑的监督。

总结一下这篇文章: