
1. 环境准备与项目配置
在开始之前,请确保您的开发环境中已配置好Java开发工具包(JDK)和Maven或Gradle等构建工具。本教程将使用JUnit 5作为测试框架,并依赖Selenium WebDriver库。
Maven pom.xml 依赖示例:
org.seleniumhq.selenium selenium-java 4.18.1 org.junit.jupiter junit-jupiter-api 5.10.1 test org.junit.jupiter junit-jupiter-engine 5.10.1 test
同时,您需要下载对应浏览器版本的WebDriver可执行文件(例如,ChromeDriver),并将其路径配置到系统属性中。
2. 登录与页面导航
首先,我们需要通过Selenium模拟用户登录并导航到包含目标表格的页面。这通常涉及定位用户名、密码输入框,输入凭据,然后点击登录按钮。
立即学习“Java免费学习笔记(深入)”;
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 org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
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 WebDriver driver;
private WebDriverWait wait;
@BeforeEach
public void setup() {
// 设置ChromeDriver路径,请替换为您的实际路径
System.setProperty("webdriver.chrome.driver", "path/to/your/chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
// 使用WebDriverWait提供更健壮的等待机制
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
@Test
public void verifyAmountColumnSorting() {
// 1. 登录到应用
driver.get("https://sakshingp.github.io/assignment/login.html");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username"))).sendKeys("Lakshay");
driver.findElement(By.id("password")).sendKeys("Wingify");
driver.findElement(By.id("log-in")).click();
// 2. 等待页面加载并导航到包含表格的页面
// 假设登录后直接跳转到 home.html,或者通过点击某个链接
wait.until(ExpectedConditions.urlContains("home.html"));
// 等待表格元素可见
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("transactionsTable")));
// ... 后续排序验证逻辑 ...
}
@AfterEach
public void tearDown() {
if (driver != null) {
driver.quit(); // 关闭浏览器
}
}
}3. 数据提取与清洗
表格数据的验证核心在于准确地从网页中提取数据,并将其转换为可比较的格式。对于金额列,通常需要移除货币符号、逗号和多余的空格,然后将字符串转换为数值类型(如Double),以便进行正确的数值排序。
我们将创建一个辅助方法 extractAndCleanAmountData() 来处理这些步骤:
/**
* 从表格中提取“Amount”列的数据并进行清洗和类型转换。
* @return 包含Double类型金额的列表。
*/
private List extractAndCleanAmountData() {
// 定位所有包含金额的span元素。这里的XPath定位了transactionsTable下tbody中所有td内的span元素。
// 请根据实际页面结构调整XPath或CSS选择器。
List amountElements = driver.findElements(By.xpath("//*[@id=\"transactionsTable\"]/tbody/tr/td/span"));
List amounts = new ArrayList<>();
for (WebElement element : amountElements) {
String text = element.getText();
// 清理字符串:移除"USD", ",", " "
String cleanedText = text.replace("USD", "")
.replace(",", "")
.trim();
try {
// 转换为Double类型进行数值比较
amounts.add(Double.parseDouble(cleanedText));
} catch (NumberFormatException e) {
System.err.println("解析金额时发生错误: " + cleanedText + " - " + e.getMessage());
// 根据需求处理错误,例如跳过此行数据或抛出异常
}
}
return amounts;
} 4. 实现排序与验证逻辑
验证表格排序的关键在于:
- 模拟点击排序按钮。
- 重新从页面上提取数据(这是验证动态排序的关键)。
- 创建一个提取数据的副本。
- 对副本进行程序化排序(例如,使用Collections.sort())。
- 比较从页面提取的实际排序数据与程序化排序后的副本数据。
验证升序排序示例:
@Test
public void verifyAmountColumnSorting() {
// ... (登录和导航代码,如上所示) ...
// 3. 点击“Amount”列头进行排序
WebElement amountHeader = driver.findElement(By.id("amount"));
amountHeader.click();
// 重要的:等待页面更新或数据重新加载。
// 对于这个页面,点击后数据会立即重新排列,但为了健壮性,可以加入短暂的等待。
// 实际项目中应使用更智能的等待,例如等待某个数据元素文本发生变化。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 4. 重新提取排序后的金额数据
List actualSortedAmounts = extractAndCleanAmountData();
System.out.println("页面实际排序后的金额: " + actualSortedAmounts);
// 5. 创建一个预期排序的列表副本并进行程序化排序
List expectedSortedAmounts = new ArrayList<>(actualSortedAmounts); // 创建副本
Collections.sort(expectedSortedAmounts); // 默认升序
System.out.println("程序化升序排序的金额: " + expectedSortedAmounts);
// 6. 验证实际数据是否与预期升序排序一致
// 假设第一次点击“Amount”按钮是升序排序。
assertEquals(expectedSortedAmounts, actualSortedAmounts, "金额列未按升序排列。");
} 验证降序排序示例(如果页面支持):
如果页面在再次点击同一列头时切换到降序排序,您可以扩展上述逻辑:
@Test
public void verifyAmountColumnDescendingSorting() {
// ... (登录和导航代码) ...
WebElement amountHeader = driver.findElement(By.id("amount"));
amountHeader.click(); // 第一次点击,假设为升序
try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
amountHeader.click(); // 第二次点击,假设为降序
try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
// 重新提取降序排序后的金额数据
List actualDescendingAmounts = extractAndCleanAmountData();
System.out.println("页面实际降序排序后的金额: " + actualDescendingAmounts);
// 创建一个副本并进行程序化降序排序
List expectedDescendingAmounts = new ArrayList<>(actualDescendingAmounts);
Collections.sort(expectedDescendingAmounts, Collections.reverseOrder()); // 降序排序
System.out.println("程序化降序排序的金额: " + expectedDescendingAmounts);
// 验证实际数据是否与预期降序排序一致
assertEquals(expectedDescendingAmounts, actualDescendingAmounts, "金额列未按降序排列。");
} 5. 注意事项与最佳实践
- 等待策略: 避免使用硬编码的 Thread.sleep()。在实际项目中,应优先使用 WebDriverWait 结合 ExpectedConditions 来等待元素可见、可点击或数据更新,以提高测试的稳定性和效率。例如,可以等待某个表格单元格的文本发生变化。
- 数据类型: 对于金额等数值数据,务必将其转换为 Double 或 BigDecimal 进行比较。直接比较字符串会进行字典序排序,可能导致 "100.00" 小于 "20.00" 的错误结果。BigDecimal 更适合处理高精度货币计算,避免浮点数精度问题。
- 元素定位器: 使用稳定且唯一的定位器(如 id、name、CSS Selector)。XPath虽然强大,但过于复杂的XPath可能因页面结构微小变化而失效。
- 代码复用: 将数据提取和清洗的逻辑封装成独立的方法,提高代码的可读性和可维护性。
- 断言信息: 在 assertEquals 等断言方法中提供清晰的错误消息,有助于快速定位问题。
- 异常处理: 在数据解析(如 Double.parseDouble())时,考虑使用 try-catch 块处理 NumberFormatException,以应对可能出现的非数字数据或格式错误。
总结
通过上述步骤,我们构建了一个健壮的Java Selenium测试脚本,能够有效地验证网页表格中金额列的升序或降序排序功能。关键在于正确地提取、清洗、转换数据,并利用程序化排序的副本与页面实际排序结果进行比较。遵循最佳实践,如使用智能等待和合适的数值类型,将使您的自动化测试更加稳定和可靠。










