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

发布于:2025-07-24 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、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中添加依赖:
    <!-- Selenium Java依赖 -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.18.0</version>
    </dependency>
    <!-- WebDriverManager(自动管理驱动) -->
    <dependency>
        <groupId>io.github.bonigarcia</groupId>
        <artifactId>webdrivermanager</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <!-- TestNG测试框架 -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.8.0</version>
        <scope>test</scope>
    </dependency>
1.2.3 浏览器驱动自动管理

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

<!-- Selenium Java依赖 -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.18.0</version>
</dependency>
<!-- WebDriverManager(自动管理驱动) -->
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
</dependency>
<!-- TestNG测试框架 -->
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.8.0</version>
    <scope>test</scope>
</dependency>

二、核心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依赖

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
  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"); // 切换到iframe
    driver.switchTo().defaultContent(); // 返回主文档

5.2 浏览器兼容性

  • Chrome For Testing:固定浏览器版本,避免自动更新影响测试:
    # 通过npm安装特定版本Chrome For Testing
    npx @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配置多线程执行测试用例:
    <suite name="ParallelSuite" parallel="methods" thread-count="5">
        <test name="Test1">
            <classes>
                <class name="tests.ShoppingTest"/>
            </classes>
        </test>
    </suite>

六、高级应用: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<String, Object> 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报告:
    <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-testng</artifactId>
        <version>2.24.0</version>
        <scope>test</scope>
    </dependency>

总结

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


网站公告

今日签到

点亮在社区的每一天
去签到