> 技术文档 > Selenium+Java 自动化测试入门到实践:从环境搭建到元素操作

Selenium+Java 自动化测试入门到实践:从环境搭建到元素操作

在自动化测试领域,Selenium 凭借其强大的跨浏览器兼容性和灵活的 API,成为 Web 应用测试的首选工具。而 Java 作为一门稳定且广泛应用的编程语言,与 Selenium 结合能构建出高效、可维护的自动化测试框架。本文将从环境搭建开始,逐步介绍 Selenium+Java 的核心用法,帮助新手快速上手。

一、环境搭建:让工具跑起来

1. 安装 Java 开发环境

Selenium 的 Java 客户端需要依赖 JDK,建议安装 JDK 8 及以上版本。安装完成后,需配置环境变量:

  • 新建JAVA_HOME,指向 JDK 安装目录(如C:\\Program Files\\Java\\jdk1.8.0_301
  • Path中添加%JAVA_HOME%\\bin%JAVA_HOME%\\jre\\bin
  • 配置CLASSPATH.;%JAVA_HOME%\\lib\\dt.jar;%JAVA_HOME%\\lib\\tools.jar

通过java -versionjavac -version命令验证安装是否成功。

2. 配置开发工具

推荐使用 IntelliJ IDEA 或 Eclipse 作为开发 IDE。以 IntelliJ IDEA 为例,新建 Maven 项目后,在pom.xml中添加 Selenium 依赖:

Maven 会自动下载 Selenium 相关的 JAR 包,无需手动导入。

3. 下载浏览器驱动

Selenium 需要通过驱动程序与浏览器交互,不同浏览器需对应不同驱动:

  • Chrome:ChromeDriver(版本需与浏览器版本匹配)
  • Firefox:GeckoDriver
  • Edge:EdgeDriver

下载后将驱动文件放在无空格的目录下(如D:\\drivers),并将该目录添加到系统Path中,或在代码中指定驱动路径。

二、第一个 Selenium+Java 程序:打开百度首页

环境就绪后,我们来编写第一个自动化脚本,实现打开 Chrome 浏览器并访问百度首页的功能:

import org.openqa.selenium.WebDriver;import org.openqa.selenium.chrome.ChromeDriver;public class FirstSeleniumTest { public static void main(String[] args) { // 初始化WebDriver实例(Chrome浏览器) WebDriver driver = new ChromeDriver(); // 打开百度首页 driver.get(\"https://www.baidu.com\"); // 打印页面标题 System.out.println(\"页面标题:\" + driver.getTitle()); // 等待3秒后关闭浏览器 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } // 关闭浏览器 driver.quit(); }}

运行代码后,会自动启动 Chrome 浏览器并打开百度首页,控制台输出页面标题,3 秒后浏览器自动关闭。这里的WebDriver是 Selenium 的核心接口,封装了浏览器的各种操作方法。

三、核心操作:元素定位与交互

自动化测试的核心是与页面元素交互,而元素定位是前提。Selenium 提供了 8 种元素定位方式,常用的有以下几种:

1. 元素定位方法

  • id:通过元素的id属性定位(唯一性高,优先使用)
    WebElement searchBox = driver.findElement(By.id(\"kw\")); // 百度搜索框
  • name:通过元素的name属性定位
    WebElement searchBox = driver.findElement(By.name(\"wd\"));
  • xpath:通过 XML 路径语言定位,支持复杂场景
    // 绝对路径(不推荐,易受页面结构变化影响)WebElement searchBtn = driver.findElement(By.xpath(\"/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input\"));// 相对路径(推荐,更灵活)WebElement searchBtn = driver.findElement(By.xpath(\"//input[@value=\'百度一下\']\"));
  • cssSelector:通过 CSS 选择器定位,速度比 xpath 快
    WebElement searchBtn = driver.findElement(By.cssSelector(\"#su\")); // 百度搜索按钮

2. 元素交互操作

定位到元素后,可执行点击、输入、清除等操作:

// 定位搜索框并输入内容WebElement searchBox = driver.findElement(By.id(\"kw\"));searchBox.sendKeys(\"Selenium+Java\");// 定位搜索按钮并点击WebElement searchBtn = driver.findElement(By.id(\"su\"));searchBtn.click();// 清除输入框内容searchBox.clear();

四、进阶技巧:等待机制与窗口切换

在实际测试中,页面加载、异步请求等可能导致元素未及时出现,直接操作会抛出异常。Selenium 提供了三种等待机制解决这一问题:

1. 等待机制

  • 隐式等待:设置全局等待时间,在规定时间内轮询查找元素
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
  • 显式等待:针对特定元素设置等待条件和超时时间
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement result = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(\"//div[contains(@class,\'result\')]\")));
  • 线程休眠:强制等待(不推荐,影响执行效率)
    Thread.sleep(2000);

2. 窗口切换

当页面打开新窗口时,需切换到对应窗口才能操作其中的元素:

// 获取当前所有窗口句柄Set windowHandles = driver.getWindowHandles();List handlesList = new ArrayList(windowHandles);// 切换到新窗口(假设新窗口是第二个打开的)driver.switchTo().window(handlesList.get(1));// 切回原窗口driver.switchTo().window(handlesList.get(0));

五、高级元素操作与 JavaScript 执行

1. 复杂表单处理

对于下拉框、复选框、单选按钮等特殊表单元素,Selenium 提供了专门的处理类:

// 处理下拉框(Select类)WebElement selectElement = driver.findElement(By.id(\"selectId\"));Select select = new Select(selectElement);// 通过索引选择(从0开始)select.selectByIndex(1);// 通过可见文本选择select.selectByVisibleText(\"选项二\");// 通过value属性选择select.selectByValue(\"option2\");// 获取所有选项List options = select.getOptions();// 处理复选框WebElement checkbox = driver.findElement(By.id(\"checkbox1\"));if (!checkbox.isSelected()) { checkbox.click();}// 处理单选按钮List radios = driver.findElement(By.name(\"radioGroup\"));for (WebElement radio : radios) { if (radio.getAttribute(\"value\").equals(\"male\")) { radio.click(); break; }}

2. 文件上传与下载

文件上传和下载是 Web 测试中常见场景:

// 文件上传(input标签type=file)WebElement uploadInput = driver.findElement(By.id(\"uploadFile\"));// 直接发送文件路径即可,无需点击上传按钮uploadInput.sendKeys(\"D:\\\\test\\\\upload.txt\");// 文件下载(配置浏览器下载路径)ChromeOptions options = new ChromeOptions();// 设置下载路径Map prefs = new HashMap();prefs.put(\"download.default_directory\", \"D:\\\\test\\\\downloads\");// 禁止下载弹窗prefs.put(\"download.prompt_for_download\", false);options.setExperimentalOption(\"prefs\", prefs);// 用配置好的选项初始化driverWebDriver driver = new ChromeDriver(options);

3. 执行 JavaScript 代码

对于 Selenium 原生 API 难以实现的操作(如滚动页面、修改元素属性),可以通过执行 JavaScript 实现:

JavascriptExecutor js = (JavascriptExecutor) driver;// 滚动到页面底部js.executeScript(\"window.scrollTo(0, document.body.scrollHeight)\");// 滚动到指定元素WebElement target = driver.findElement(By.id(\"targetId\"));js.executeScript(\"arguments[0].scrollIntoView();\", target);// 修改元素属性(如移除readonly属性)js.executeScript(\"arguments[0].removeAttribute(\'readonly\')\", element);// 获取页面标题(通过JS)String title = (String) js.executeScript(\"return document.title\");

六、测试框架设计与优化

1. 基础框架结构

一个规范的 Selenium 测试框架应包含以下结构:

src/main/java├── common/  // 公共工具类│ ├── DriverUtil.java // 驱动管理│ ├── WaitUtil.java // 等待工具│ └── ScreenShotUtil.java // 截图工具├── page/ // 页面对象│ ├── LoginPage.java│ └── HomePage.java└── test/ // 测试用例 ├── LoginTest.java └── HomeTest.java

2. 页面对象模型(POM)

POM 模式将页面元素和操作封装到页面对象类中,提高代码复用性和可维护性:

// 登录页面对象public class LoginPage { private WebDriver driver; private WebDriverWait wait; // 元素定位 @FindBy(id = \"username\") private WebElement usernameInput; @FindBy(id = \"password\") private WebElement passwordInput; @FindBy(id = \"loginBtn\") private WebElement loginButton; // 构造方法 public LoginPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); PageFactory.initElements(driver, this); // 初始化页面元素 } // 页面操作 public void enterUsername(String username) { usernameInput.sendKeys(username); } public void enterPassword(String password) { passwordInput.sendKeys(password); } public HomePage clickLogin() { loginButton.click(); return new HomePage(driver); // 登录后跳转到首页 } public void login(String username, String password) { enterUsername(username); enterPassword(password); clickLogin(); }}

使用 POM 后的测试用例更加简洁:

public class LoginTest { private WebDriver driver; private LoginPage loginPage; @BeforeEach public void setUp() { driver = DriverUtil.getDriver(); driver.get(\"https://example.com/login\"); loginPage = new LoginPage(driver); } @Test public void testSuccessfulLogin() { loginPage.login(\"testuser\", \"testpass\"); // 验证登录成功 Assertions.assertTrue(driver.getCurrentUrl().contains(\"/home\")); } @AfterEach public void tearDown() { DriverUtil.quitDriver(); }}

3. 数据驱动测试

结合 TestNG 和 Excel 实现数据驱动测试,用不同数据执行相同测试逻辑:

// 读取Excel数据工具类public class ExcelUtil { public static Object[][] readTestData(String filePath, String sheetName) { // 实现Excel读取逻辑,返回二维数组 // 每行代表一组测试数据,每列代表一个参数 }}// 数据驱动测试用例public class LoginDataDrivenTest { private WebDriver driver; private LoginPage loginPage; @BeforeMethod public void setUp() { driver = DriverUtil.getDriver(); driver.get(\"https://example.com/login\"); loginPage = new LoginPage(driver); } @Test(dataProvider = \"loginData\") public void testLoginWithDifferentData(String username, String password, String expectedResult) { loginPage.enterUsername(username); loginPage.enterPassword(password); loginPage.clickLogin(); if (expectedResult.equals(\"success\")) { Assertions.assertTrue(driver.getCurrentUrl().contains(\"/home\")); } else { Assertions.assertTrue(driver.findElement(By.cssSelector(\".error-msg\")).isDisplayed()); } } @DataProvider(name = \"loginData\") public Object[][] provideTestData() { return ExcelUtil.readTestData(\"src/test/resources/loginData.xlsx\", \"Sheet1\"); } @AfterMethod public void tearDown() { DriverUtil.quitDriver(); }}

七、测试报告与持续集成

1. 生成美观的测试报告

使用 ExtentReports 生成详细的 HTML 测试报告:

public class ExtentReportUtil { private static ExtentReports extent; private static ExtentTest test; public static void initReport() { extent = new ExtentReports(); File reportDir = new File(\"test-reports\"); if (!reportDir.exists()) { reportDir.mkdir(); } ExtentSparkReporter spark = new ExtentSparkReporter(\"test-reports/result.html\"); extent.attachReporter(spark); } public static void createTest(String testName) { test = extent.createTest(testName); } public static void logPass(String message) { test.pass(message); } public static void logFail(String message) { test.fail(message); // 失败时截图 String screenshotPath = ScreenShotUtil.takeScreenshot(driver, \"fail\"); test.addScreenCaptureFromPath(screenshotPath); } public static void flushReport() { extent.flush(); }}

2. 集成到 CI/CD 流程

将 Selenium 测试集成到 Jenkins 等 CI 工具,实现自动化构建和测试:

  1. 在项目中添加 Maven Surefire 插件,用于执行测试用例:
   org.apache.maven.plugins maven-surefire-plugin 3.0.0-M5    src/test/resources/testng.xml    
  1. 在 Jenkins 中配置:
    • 拉取代码仓库
    • 执行mvn clean test命令
    • 配置测试报告展示(ExtentReports 或 TestNG 报告)
    • 设置邮件通知,发送测试结果

八、常见问题与解决方案

1. 元素定位不稳定

  • 优先使用显式等待,而非隐式等待或线程休眠
  • 避免使用绝对 XPath,改用相对 XPath 并结合多种属性定位
  • 对于动态 ID,使用包含部分固定文本的定位方式://div[contains(@id, \'prefix_\')]

2. 浏览器兼容性问题

  • 使用 WebDriverManager 管理不同浏览器驱动,自动匹配版本:
WebDriverManager.chromedriver().setup();WebDriver driver = new ChromeDriver();
  • 编写测试基类,通过参数控制启动不同浏览器:
public class TestBase { protected WebDriver driver; @Parameters(\"browser\") @BeforeMethod public void setUp(String browser) { if (browser.equals(\"chrome\")) { driver = new ChromeDriver(); } else if (browser.equals(\"firefox\")) { driver = new FirefoxDriver(); } else if (browser.equals(\"edge\")) { driver = new EdgeDriver(); } driver.manage().window().maximize(); }}

3. 执行速度优化

  • 减少不必要的等待时间,合理设置超时参数
  • 避免在循环中频繁查找元素,可一次查找后缓存
  • 使用 Headless 模式运行浏览器(无界面模式):
ChromeOptions options = new ChromeOptions();options.addArguments(\"--headless=new\"); // Chrome 112+版本WebDriver driver = new ChromeDriver(options);

九、总结与学习资源

Selenium+Java 的学习是一个循序渐进的过程,从基础操作到框架搭建需要不断实践和总结

自动化测试的核心价值在于提高测试效率和回归测试覆盖率,在实际项目中,应根据需求选择合适的测试场景进行自动化,避免盲目追求自动化率。随着经验的积累,你会逐渐掌握如何设计出稳定、高效、易维护的自动化测试框架。