Selenium Java:验证网页表格数据排序功能

本教程详细介绍了如何使用 Java 和 Selenium WebDriver 自动化测试网页表格中数值列的排序功能。文章涵盖了从元素定位、数据提取、清洗转换到排序验证的完整流程,并通过示例代码演示了如何验证升序和降序排列,确保数据一致性。

1. 引言与背景

在 Web 应用测试中,表格数据的排序功能是常见的测试点之一。用户通常期望点击列标题后,表格数据能按照该列的数值或字母顺序正确排列。手动验证大量数据不仅耗时且易出错,因此,使用 Selenium 自动化验证表格排序功能变得尤为重要。本教程将以一个具体的“金额”列为例,演示如何使用 Java 和 Selenium 验证表格数据的升序和降序排列。

2. 环境准备

在开始之前,请确保您的开发环境已配置以下组件:

  • Java Development Kit (JDK):版本 8 或更高。
  • Maven 或 Gradle:用于项目管理和依赖管理。
  • Selenium WebDriver:核心自动化库。
  • JUnit 或 TestNG:测试框架。
  • ChromeDriver:或其他浏览器驱动(如 GeckoDriver for Firefox),与您的浏览器版本匹配。

Maven pom.xml 依赖示例:


    
    
        org.seleniumhq.selenium
        selenium-java
        4.1.2 
    
    
    
        junit
        junit
        4.13.2
        test
    
    
    
        io.github.bonigarcia
        webdrivermanager
        5.0.3 
        test
    

3. 核心验证步骤

验证表格数据排序通常涉及以下几个关键步骤:

3.1 初始化 WebDriver 并导航

首先,需要设置 WebDriver 并导航到包含目标表格的网页。这通常包括浏览器启动、最大化窗口以及登录等操作。

3.2 提取原始数据

在执行任何排序操作之前,我们需要获取表格中目标列的当前数据。这些数据将作为我们生成预期排序结果的基准。

3.3 数据清洗与类型转换

从网页元素中提取的文本数据通常包含货币符号、逗号、空格等非数字字符。为了能够进行数值排序,必须对这些字符串进行清洗,并将其转换为可比较的数值类型(如 Double)。

3.4 准备预期排序数据

基于清洗后的原始数值列表,我们可以使用 Java 的 Collections.sort() 方法生成一个预期升序排列的列表。如果需要验证降序,则可以对升序列表进行反转。

3.5 触发 UI 排序操作

通过 Selenium 定位并点击表格列的标题元素,以触发网页的内置排序功能。

3.6 提取实际排序数据

点击排序按钮后,再次从表格中提取目标列的文本数据,并进行相同的清洗和类型转换,得到实际的排序结果。

3.7 执行断言验证

最后,使用断言(如 Assert.assertEquals())比较实际排序结果列表与预期排序结果列表。如果两者完全相同,则表示排序功能正常。

4. 示例代码:验证“金额”列排序

以下是一个完整的 Java Selenium JUnit 测试示例,用于验证指定网页上“金额”列的升序和降序排序功能。

package com.example.seleniumtests;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
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.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class TableSortingVerification {

    private static WebDriver driver;
    private static WebDriverWait wait;

    // 辅助方法:提取并清洗金额数据
    private List extractAndCleanAmountData() {
        // 定位所有金额列的span元素
        List amountElements = driver.findElements(By.xpath("//table[@id='transactionsTable']/tbody/tr/td/span"));
        List cleanedAmounts = new ArrayList<>();

        for (WebElement element : amountElements) {
            String text = element.getText();
            // 清除货币符号 "USD", 逗号 ",",

空格 " " String cleanedText = text.replaceAll("USD", "").replaceAll(",", "").trim(); try { // 转换为 Double 类型 cleanedAmounts.add(Double.parseDouble(cleanedText)); } catch (NumberFormatException e) { System.err.println("无法解析金额: " + text + " - " + e.getMessage()); // 根据需求处理错误,例如跳过或抛出异常 } } return cleanedAmounts; } @BeforeClass public static void setup() { // 自动管理 ChromeDriver (推荐使用 WebDriverManager) WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(); driver.manage().window().maximize(); wait = new WebDriverWait(driver, Duration.ofSeconds(10)); // 显式等待 // 导航到登录页面并登录 String loginUrl = "https://sakshingp.github.io/assignment/login.html"; driver.get(loginUrl); wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username"))).sendKeys("Lakshay"); driver.findElement(By.id("password")).sendKeys("Wingify"); driver.findElement(By.id("log-in")).click(); // 等待登录成功并跳转到主页 wait.until(ExpectedConditions.urlContains("home.html")); System.out.println("成功登录并进入主页."); } @Test public void testAmountColumnSorting() { System.out.println("开始验证金额列排序..."); // 1. 提取原始(未排序)金额数据 List initialAmounts = extractAndCleanAmountData(); System.out.println("原始金额数据: " + initialAmounts); // 2. 准备预期升序数据 List expectedAscendingAmounts = new ArrayList<>(initialAmounts); Collections.sort(expectedAscendingAmounts); // 默认升序 System.out.println("预期升序数据: " + expectedAscendingAmounts); // 3. 触发 UI 升序排序操作 WebElement amountHeader = driver.findElement(By.id("amount")); amountHeader.click(); // 第一次点击通常是升序 // 4. 提取实际升序排序后的数据 // 等待表格内容更新,这里可以根据实际页面加载情况调整等待策略 // 简单等待一段时间,或者等待某个元素状态变化 wait.until(ExpectedConditions.stalenessOf(amountHeader)); // 假设点击后页面有刷新或部分更新 wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//table[@id='transactionsTable']/tbody/tr/td/span"))); // 确保元素可见 List actualAscendingAmounts = extractAndCleanAmountData(); System.out.println("实际升序数据: " + actualAscendingAmounts); // 5. 验证升序排序 Assert.assertEquals("金额列升序排序验证失败!", expectedAscendingAmounts, actualAscendingAmounts); System.out.println("金额列升序排序验证成功!"); // --- 验证降序排序(可选) --- System.out.println("\n开始验证金额列降序排序..."); // 1. 准备预期降序数据 List expectedDescendingAmounts = new ArrayList<>(expectedAscendingAmounts); Collections.reverse(expectedDescendingAmounts); // 反转升序列表得到降序 System.out.println("预期降序数据: " + expectedDescendingAmounts); // 2. 触发 UI 降序排序操作 (再次点击通常是降序) amountHeader.click(); // 3. 提取实际降序排序后的数据 wait.until(ExpectedConditions.stalenessOf(amountHeader)); // 假设点击后页面有刷新或部分更新 wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//table[@id='transactionsTable']/tbody/tr/td/span"))); // 确保元素可见 List actualDescendingAmounts = extractAndCleanAmountData(); System.out.println("实际降序数据: " + actualDescendingAmounts); // 4. 验证降序排序 Assert.assertEquals("金额列降序排序验证失败!", expectedDescendingAmounts, actualDescendingAmounts); System.out.println("金额列降序排序验证成功!"); } @AfterClass public static void tearDown() { if (driver != null) { driver.quit(); System.out.println("浏览器已关闭."); } } }

5. 注意事项与最佳实践

  • 等待策略:在 Selenium 自动化中,等待是至关重要的。本示例使用了 WebDriverWait 显式等待,确保元素可见或页面加载完成。避免使用 Thread.sleep(),因为它会导致测试不稳定和效率低下。
  • 数据清洗的健壮性:replaceAll() 方法能够很好地处理字符串中的特定字符。如果金额格式更复杂(例如,包含多种货币符号、负号位置不同等),可能需要更复杂的正则表达式或自定义解析逻辑。
  • 异常处理:在将字符串转换为 Double 时,务必捕获 NumberFormatException。这可以防止因页面上出现非数字文本而导致测试崩溃。
  • 定位器策略:本示例使用了 XPath (//table[@id='transactionsTable']/tbody/tr/td/span) 来定位金额列。选择稳定且具有唯一性的定位器(如 ID、CSS Selector 或更具体的 XPath)对于测试的健壮性至关重要。避免使用过于脆弱的定位器,如绝对 XPath。
  • 升序/降序逻辑:通常,第一次点击列标题是升序,第二次点击是降序。如果页面行为不同,需要调整测试逻辑。
  • 动态表格内容:如果表格内容是动态加载的(例如,通过 AJAX),确保在提取数据前有足够的等待时间,以确保所有数据都已加载并呈现在 DOM 中。
  • 代码可读性与复用:将数据提取和清洗逻辑封装到单独的辅助方法中(如 extractAndCleanAmountData()),可以提高代码的可读性和复用性。

6. 总结

通过本教程,您应该掌握了如何使用 Java 和 Selenium WebDriver 自动化验证网页表格的排序功能。核心在于正确地提取、清洗和转换数据,然后与预期排序结果进行比较。这种自动化测试方法不仅提高了测试效率,也大大增强了测试的准确性和可靠性,确保了 Web 应用数据展示的正确性。