> 技术文档 > 【自动化测试】Selenium Java UI自动化测试实用教程

【自动化测试】Selenium Java UI自动化测试实用教程


一、Selenium基础理论与环境搭建

1.1 Selenium简介与核心组件

Selenium是一个开源的Web自动化测试框架,支持多浏览器、多语言(Java、Python等),核心组件包括:

  • WebDriver:通过浏览器驱动直接控制浏览器,模拟用户操作(点击、输入等),无侵入性。
  • IDE:浏览器插件,支持录制/回放操作,适合快速生成脚本。
  • Grid:分布式测试工具,支持多节点并行执行测试用例,提升效率。

Selenium 4.x(2025年最新版本为4.18)的核心特性包括:

  • W3C WebDriver协议标准化:无需JSON Wire协议编解码,直接与浏览器通信,稳定性提升。
  • Chrome DevTools Protocol(CDP)支持:原生集成网络监控、性能分析、地理位置模拟等高级功能。
  • 相对定位器:通过above()below()toLeftOf()等方法基于元素相对位置定位。
  • Selenium Manager:自动管理浏览器驱动(如ChromeDriver),无需手动下载配置。

1.2 环境搭建步骤

1.2.1 Java环境配置
  1. 安装JDK:推荐Java 11+,从Oracle官网下载对应版本,安装时勾选“Add to PATH”。
  2. 验证安装:命令行输入java -version,输出类似java version \"17.0.10\"即成功。
1.2.2 Maven项目配置
  1. 创建Maven项目:使用IDE(如IntelliJ IDEA)创建Maven项目,在pom.xml中添加依赖:
     org.seleniumhq.selenium selenium-java 4.18.0 io.github.bonigarcia webdrivermanager 5.6.0 test org.testng testng 7.8.0 test
1.2.3 浏览器驱动自动管理

通过WebDriverManager自动下载并配置驱动,无需手动管理版本:

 org.seleniumhq.selenium selenium-java 4.18.0 io.github.bonigarcia webdrivermanager 5.6.0 test org.testng testng 7.8.0 test

二、核心API与元素操作

2.1 元素定位策略

Selenium提供8种定位方式,按优先级排序如下:

定位方式 语法示例 适用场景 ID driver.findElement(By.id(\"kw\")) 元素有唯一ID属性 CSS选择器 driver.findElement(By.cssSelector(\".s_ipt\")) 复杂样式匹配或动态属性 XPath driver.findElement(By.xpath(\"//input[@name=\'wd\']\")) 无固定属性时灵活定位 相对定位器(Selenium 4+) driver.findElement(withTagName(\"input\").below(usernameInput)) 基于相邻元素位置定位

示例:使用XPath定位百度搜索框并输入文本

import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebElement;import org.openqa.selenium.chrome.ChromeDriver;import io.github.bonigarcia.wdm.WebDriverManager;public class ElementLocation { public static void main(String[] args) { WebDriverManager.chromedriver().setup(); WebDriver driver = new ChromeDriver(); driver.get(\"https://www.baidu.com\"); // XPath定位搜索框并输入\"selenium\" WebElement searchBox = driver.findElement(By.xpath(\"//input[@id=\'kw\']\")); searchBox.sendKeys(\"selenium\"); // CSS选择器定位搜索按钮并点击 WebElement searchBtn = driver.findElement(By.cssSelector(\"#su\")); searchBtn.click(); driver.quit(); }}

2.2 浏览器控制与等待机制

2.2.1 浏览器操作
import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebElement;import org.openqa.selenium.chrome.ChromeDriver;import io.github.bonigarcia.wdm.WebDriverManager;public class ElementLocation { public static void main(String[] args) { WebDriverManager.chromedriver().setup(); WebDriver driver = new ChromeDriver(); driver.get(\"https://www.baidu.com\"); // XPath定位搜索框并输入\"selenium\" WebElement searchBox = driver.findElement(By.xpath(\"//input[@id=\'kw\']\")); searchBox.sendKeys(\"selenium\"); // CSS选择器定位搜索按钮并点击 WebElement searchBtn = driver.findElement(By.cssSelector(\"#su\")); searchBtn.click(); driver.quit(); }}
2.2.2 等待策略(解决动态元素加载问题)
  • 隐式等待:全局设置,对所有元素查找生效
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
  • 显式等待:针对特定元素设置条件等待
  • import org.openqa.selenium.support.ui.WebDriverWait;import org.openqa.selenium.support.ui.ExpectedConditions;WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement dynamicElement = wait.until( ExpectedConditions.visibilityOfElementLocated(By.id(\"dynamicElement\")));

2.3 高级交互:Actions类

模拟鼠标、键盘操作(如拖拽、右键点击):

import org.openqa.selenium.support.ui.WebDriverWait;import org.openqa.selenium.support.ui.ExpectedConditions;WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement dynamicElement = wait.until( ExpectedConditions.visibilityOfElementLocated(By.id(\"dynamicElement\")));

三、高级设计模式:PO模式与数据驱动

3.1 Page Object Model(PO模式)

核心思想:将页面元素和操作封装为类,实现测试逻辑与页面细节分离,提升代码复用性和维护性。

3.1.1 目录结构
src/test/java├── pages // 页面对象类│ ├── BasePage.java // 基类,封装公共方法│ ├── LoginPage.java // 登录页面对象│ └── HomePage.java // 首页面对象└── tests  // 测试用例 └── LoginTest.java // 登录测试
3.1.2 实现示例

BasePage.java(基类)

import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebElement;import org.openqa.selenium.support.ui.WebDriverWait;import org.openqa.selenium.support.ui.ExpectedConditions;import java.time.Duration;public class BasePage { protected WebDriver driver; protected WebDriverWait wait; public BasePage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } // 封装元素等待与点击 protected void click(WebElement element) { wait.until(ExpectedConditions.elementToBeClickable(element)).click(); } // 封装元素输入 protected void sendKeys(WebElement element, String text) { wait.until(ExpectedConditions.visibilityOf(element)).sendKeys(text); }}

LoginPage.java(登录页面对象)

import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebElement;public class LoginPage extends BasePage { // 元素定位 private By usernameInput = By.id(\"username\"); private By passwordInput = By.id(\"password\"); private By loginBtn = By.id(\"loginBtn\"); public LoginPage(WebDriver driver) { super(driver); } // 页面操作 public void inputUsername(String username) { WebElement element = driver.findElement(usernameInput); sendKeys(element, username); } public void inputPassword(String password) { WebElement element = driver.findElement(passwordInput); sendKeys(element, password); } public HomePage clickLoginBtn() { WebElement element = driver.findElement(loginBtn); click(element); return new HomePage(driver); // 跳转到首页 }}

LoginTest.java(测试用例)

import org.openqa.selenium.WebDriver;import org.openqa.selenium.chrome.ChromeDriver;import org.testng.annotations.AfterMethod;import org.testng.annotations.BeforeMethod;import org.testng.annotations.Test;import io.github.bonigarcia.wdm.WebDriverManager;public class LoginTest { private WebDriver driver; @BeforeMethod public void setup() { WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(); driver.get(\"https://example.com/login\"); } @Test public void testValidLogin() { LoginPage loginPage = new LoginPage(driver); loginPage.inputUsername(\"testuser\"); loginPage.inputPassword(\"testpass\"); HomePage homePage = loginPage.clickLoginBtn(); // 断言登录成功(示例) assert homePage.getWelcomeText().contains(\"Welcome\"); } @AfterMethod public void teardown() { if (driver != null) { driver.quit(); } }}

3.2 数据驱动测试(DDT)

核心思想:测试数据与脚本分离,通过外部文件(Excel、CSV)或数据库驱动测试用例,覆盖多场景。

3.2.1 使用TestNG的@DataProvider
import org.testng.annotations.DataProvider;import org.testng.annotations.Test;public class DataDrivenTest { // 数据提供者:返回二维数组(测试数据) @DataProvider(name = \"loginData\") public Object[][] provideData() { return new Object[][]{ {\"validUser\", \"validPass\", \"登录成功\"}, {\"invalidUser\", \"invalidPass\", \"用户名或密码错误\"} }; } // 测试方法:使用数据提供者 @Test(dataProvider = \"loginData\") public void testLogin(String username, String password, String expectedResult) { // 执行登录操作并验证结果 System.out.println(\"用户名:\" + username + \",预期结果:\" + expectedResult); }}
3.2.2 读取Excel数据(Apache POI)
  1. 添加POI依赖

     org.apache.poi poi-ooxml 5.2.3
  2. Excel读取工具类

    import org.apache.poi.ss.usermodel.*;import java.io.FileInputStream;import java.io.IOException;public class ExcelUtil { public static Object[][] readExcel(String filePath, String sheetName) throws IOException { Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath)); Sheet sheet = workbook.getSheet(sheetName); int rowCount = sheet.getPhysicalNumberOfRows(); int colCount = sheet.getRow(0).getPhysicalNumberOfCells(); Object[][] data = new Object[rowCount - 1][colCount]; for (int i = 1; i < rowCount; i++) { Row row = sheet.getRow(i); for (int j = 0; j < colCount; j++) { Cell cell = row.getCell(j); data[i - 1][j] = cell.getStringCellValue(); } } workbook.close(); return data; }}
  3. 测试用例集成

    @DataProvider(name = \"excelData\")public Object[][] getExcelData() throws IOException { return ExcelUtil.readExcel(\"src/test/resources/loginData.xlsx\", \"Sheet1\");}@Test(dataProvider = \"excelData\")public void testLoginWithExcel(String username, String password, String expected) { // 执行测试逻辑}

四、项目实战:电商网站登录与购物流程

4.1 项目结构

src/test/java├── pages // 页面对象│ ├── LoginPage.java│ ├── HomePage.java│ ├── ProductPage.java│ └── CartPage.java├── tests // 测试用例│ ├── LoginTest.java│ └── ShoppingTest.java├── utils // 工具类│ ├── ExcelUtil.java│ └── LogUtil.java└── resources // 测试数据 └── testData.xlsx

4.2 核心场景实现:商品加入购物车

public class ShoppingTest { private WebDriver driver; private LoginPage loginPage; private HomePage homePage; private ProductPage productPage; private CartPage cartPage; @BeforeMethod public void setup() { WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(); driver.manage().window().maximize(); loginPage = new LoginPage(driver); homePage = new HomePage(driver); productPage = new ProductPage(driver); cartPage = new CartPage(driver); } @Test(dataProvider = \"productData\", dataProviderClass = ExcelUtil.class) public void testAddToCart(String username, String password, String productName) { // 登录 driver.get(\"https://example.com/login\"); loginPage.inputUsername(username); loginPage.inputPassword(password); loginPage.clickLoginBtn(); // 搜索商品 homePage.searchProduct(productName); homePage.clickSearchResult(productName); // 加入购物车 productPage.clickAddToCart(); // 验证购物车 cartPage.gotoCart(); assert cartPage.isProductInCart(productName); } @AfterMethod public void teardown() { driver.quit(); }}

五、常见问题与解决方案

5.1 元素定位失败

  • 动态ID/属性:使用XPath/CSS模糊匹配(如contains(@class, \'btn\'))。
  • iframe嵌套:先切换到iframe再操作元素:
    driver.switchTo().frame(\"iframeId\"); // 切换到iframedriver.switchTo().defaultContent(); // 返回主文档

5.2 浏览器兼容性

  • Chrome For Testing:固定浏览器版本,避免自动更新影响测试:
    # 通过npm安装特定版本Chrome For Testingnpx @puppeteer/browsers install chrome@120.0.6099.0

5.3 测试速度优化

  • Headless模式:无界面运行浏览器,节省资源:
    ChromeOptions options = new ChromeOptions();options.addArguments(\"--headless=new\"); // Selenium 4.10+语法WebDriver driver = new ChromeDriver(options);
  • 并行执行:TestNG配置多线程执行测试用例:
         

六、高级应用:CDP协议与持续集成

6.1 Chrome DevTools Protocol(CDP)

模拟网络条件、地理位置等高级功能:

import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.devtools.DevTools;import java.util.HashMap;import java.util.Map;public class CDPExample { public static void main(String[] args) { WebDriver driver = new ChromeDriver(); DevTools devTools = ((ChromeDriver) driver).getDevTools(); devTools.createSession(); // 模拟5G网络 Map networkConditions = new HashMap(); networkConditions.put(\"offline\", false); networkConditions.put(\"latency\", 20); // 延迟20ms networkConditions.put(\"downloadThroughput\", 20 * 1024 * 1024); // 20Mbps driver.executeCdpCommand(\"Network.emulateNetworkConditions\", networkConditions); driver.get(\"https://example.com\"); driver.quit(); }}

6.2 持续集成(Jenkins)

  1. 配置Jenkins任务:拉取代码 → 执行Maven命令(mvn test)。
  2. 生成测试报告:TestNG默认生成报告,或集成Allure报告:
     io.qameta.allure allure-testng 2.24.0 test

总结

本教程从基础环境搭建到高级设计模式,全面覆盖了Selenium Java版UI自动化测试的核心知识点。通过PO模式实现代码解耦,结合数据驱动提升测试覆盖率,配合CDP协议和持续集成构建企业级测试框架。实际应用中需注意元素定位策略优化、动态内容处理及测试效率提升,逐步构建稳定、可维护的自动化测试体系。