如何使用Selenium Java计算无XPath/CSS定位的加载Spinner显示时长?
如何用Selenium Java计算无定位符的加载Spinner显示时长
嘿,这个问题我之前也碰到过——没有专属XPath或CSS定位符的Spinner确实有点棘手,但咱们可以从UI状态关联变化或者绑定的后端HTTP请求这两个核心角度来解决,下面给你具体的实现思路和代码示例:
方案一:基于UI关联元素的状态变化
如果Spinner没有直接定位符,它大概率会和某个你能定位到的元素绑定状态(比如触发按钮的禁用状态、Spinner所在容器的类名变化等)。咱们可以通过监控这个关联元素的状态变化来计算时长。
实现步骤:
- 找到能触发Spinner的按钮(这个按钮肯定能定位到吧😉),以及Spinner所在的父容器(如果有的话)。
- 点击按钮前记录开始时间戳。
- 点击按钮触发请求和Spinner显示。
- 轮询等待,直到关联元素的状态恢复到Spinner出现前的状态(比如容器的
loading类被移除、按钮恢复可点击)。 - 记录结束时间戳,计算两者的差值就是Spinner的显示时长。
代码示例:
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; public class SpinnerDurationCalculator { public static void main(String[] args) { // 初始化ChromeDriver(记得配置好驱动路径) WebDriver driver = new ChromeDriver(); driver.get("你的应用页面URL"); // 定位触发Spinner的按钮(假设这个按钮有ID定位符) WebElement triggerButton = driver.findElement(By.id("submit-btn")); // 定位Spinner所在的父容器(假设容器有ID) WebElement spinnerContainer = driver.findElement(By.id("content-container")); // 记录Spinner开始显示的时间 long startTime = System.currentTimeMillis(); // 点击按钮触发请求和Spinner triggerButton.click(); // 等待Spinner消失:这里监听容器的class是否移除了"loading"标识 WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.not(ExpectedConditions.attributeContains(spinnerContainer, "class", "loading"))); // 记录Spinner消失的时间 long endTime = System.currentTimeMillis(); // 计算并打印时长 long displayDuration = endTime - startTime; System.out.println("Spinner显示时长:" + displayDuration + " 毫秒"); driver.quit(); } }
方案二:基于后端HTTP请求的完成时机
因为Spinner的显示和后端请求强绑定,请求完成后Spinner才会消失,所以咱们可以通过监听对应的HTTP请求完成事件来计算时长,这个方法甚至不需要关心Spinner的UI定位。
实现步骤:
- 初始化ChromeDriver并开启Chrome DevTools(用来监听网络请求)。
- 启用网络监控,监听目标后端请求的完成事件。
- 点击按钮前记录开始时间戳。
- 点击按钮触发请求,等待目标请求完成。
- 记录结束时间戳,计算时长。
代码示例:
import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.v120.network.Network; import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; public class SpinnerDurationWithNetwork { public static void main(String[] args) throws InterruptedException { ChromeDriver driver = new ChromeDriver(); driver.get("你的应用页面URL"); // 开启DevTools会话 DevTools devTools = driver.getDevTools(); devTools.createSession(); // 启用网络监控 devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); // 用CountDownLatch来等待请求完成 CountDownLatch requestCompleted = new CountDownLatch(1); // 替换成你要监听的后端请求URL(可以是部分匹配) String targetApiUrl = "https://your-backend.com/api/data-submit"; // 监听请求完成事件 devTools.addListener(Network.responseReceived(), response -> { String requestUrl = response.getResponse().getUrl(); if (requestUrl.contains(targetApiUrl)) { requestCompleted.countDown(); } }); WebElement triggerButton = driver.findElement(By.id("submit-btn")); long startTime = System.currentTimeMillis(); // 触发请求 triggerButton.click(); // 等待目标请求完成(超时时间10秒) requestCompleted.await(10, TimeUnit.SECONDS); long endTime = System.currentTimeMillis(); long displayDuration = endTime - startTime; System.out.println("Spinner显示时长(基于网络请求):" + displayDuration + " 毫秒"); // 关闭网络监控 devTools.send(Network.disable()); driver.quit(); } }
补充说明:
如果连父容器都找不到,还可以考虑监控页面的document.readyState或者某个元素的文本变化,但这些方法的稳定性不如上面两种。视觉对比(比如用Ashot库对比页面截图)虽然可行,但容易受页面其他元素变化影响,不推荐作为首选。
内容的提问来源于stack exchange,提问作者Milind Wadhwa
相关产品推荐
相关产品推荐

