基于Selenium+Browsermob+Browserstack的空HAR文件问题排查
解决BrowserMob Proxy + Selenium(BrowserStack)生成空HAR文件的问题
我帮你分析了下你遇到的BrowserMob Proxy生成空HAR的问题,核心原因是BrowserMob Proxy没有和RemoteWebDriver的代理配置正确绑定,再加上录制时机的顺序错误,导致代理根本没捕获到任何请求。下面是具体的排查点和修复方案:
问题代码中的关键错误
- 在
setUp类的setCapabilities方法中,你初始化RemoteWebDriver时用的是未添加代理配置的DesiredCapabilities,而testIndex类的BeforeSuite里单独创建的带代理的capabilities完全没用到 - 代理启动、HAR录制和WebDriver初始化的顺序颠倒:你先创建了HAR,再启动代理,最后才初始化WebDriver,导致录制的是代理启动前的空流量
- BrowserStack Local的配置和代理没有协同,可能导致流量没经过代理
具体修复步骤
1. 调整代理与WebDriver的绑定逻辑
把代理的启动、配置移到setUp类的setCapabilities方法中,确保WebDriver启动时就使用带代理的capabilities:
@BeforeClass (alwaysRun = true) @Parameters(value = { "browser", "version", "os", "os_version", "project", "build" }) protected void setCapabilities(String browser, String version, String os, String os_version, String project, String build) throws MalformedURLException, UnexpectedException { // 第一步:启动BrowserMob Proxy并配置捕获规则 proxy.start(); // 捕获所有类型的内容,包括Analytics请求 proxy.setHarCaptureTypes(CaptureType.getAllContentCaptureTypes()); proxy.enableHarCaptureTypes(CaptureType.getAllContentCaptureTypes()); // 第二步:创建Selenium兼容的代理对象并添加到DesiredCapabilities Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy); DesiredCapabilities capability = new DesiredCapabilities(); capability.setCapability(CapabilityType.PROXY, seleniumProxy); // 原有BrowserStack能力配置保持不变 capability.setCapability("browserName", browser); capability.setCapability("browserVersion", version); capability.setCapability("os", os); capability.setCapability("os_version", os_version); capability.setCapability("project", project); capability.setCapability("build", build); capability.setCapability("browserstack.debug", "true"); capability.setCapability("browserstack.console", "warnings"); capability.setCapability("resolution", "1920x1080"); capability.setCapability("browserstack.local", "true"); capability.setCapability("browserstack.localIdentifier", "Test123"); capability.setCapability("browserstack.safari.enablePopups", "true"); capability.setCapability("browserstack.safari.allowAllCookies", "true"); capability.setCapability(CapabilityType.SUPPORTS_JAVASCRIPT, "true"); capability.setCapability(CapabilityType.ACCEPT_SSL_CERTS, "true"); capability.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, "true"); capability.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, "true"); capability.setCapability("browserstack.ie.enablePopups", "true"); capability.setCapability("browserstack.edge.enablePopups", "true"); capability.setCapability("unexpectedAlertBehaviour", "accept"); capability.setCapability("ignoreProtectedModeSettings", "true"); capability.setCapability("enablePersistentHover", "true"); capability.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING, "true"); capability.setCapability("browserstack.use_w3c", "true"); capability.setCapability("browserstack.maskSendKeys", "true"); Credentials.PropertyFile.setCapabilities(capability); // 第三步:初始化RemoteWebDriver,此时已绑定代理 webDriver.set(new RemoteWebDriver(new URL(Credentials.PropertyFile.getBrowserstackURL()), capability)); EnvironmentErrors(); }
2. 调整HAR录制时机
必须在WebDriver访问页面之前启动HAR录制,确保捕获到页面加载及后续的所有请求:
public static void TestSetup() throws InterruptedException, UnknownHostException { Capabilities cap = ((RemoteWebDriver) webDriver.get()).getCapabilities(); String browserName = cap.getBrowserName().toString(); // 先启动HAR录制,再访问目标URL proxy.newHar("Analytics"); webDriver.get().get(WebURL); // 建议替换Thread.sleep为显式等待,等待页面加载完成或Analytics请求发送 Thread.sleep(10000); System.out.println(ANSI_WHITE + webDriver.get().getTitle() + (" Being tested on: ") + ANSI_GREEN + Environment + ANSI_WHITE + (" and ") + ANSI_GREEN + browserName + (" browser!")); webDriver.get().manage().window().maximize(); Thread.sleep(5000); // 获取并打印HAR内容 Har har = proxy.getHar(); java.io.StringWriter writer = new java.io.StringWriter(); try { har.writeTo(writer); } catch (IOException e) { e.printStackTrace(); } String harAsString = writer.toString(); System.out.println(IndexElements.ANSI_BLUE + "=======CONSOLE=======" + harAsString); }
3. 清理冗余代码
删掉testIndex类BeforeSuite中重复的代理和capabilities配置,因为现在所有逻辑都在setUp类中处理了:
@BeforeSuite(alwaysRun = true) public static void main() throws InterruptedException, UnknownHostException { // 此处无需再初始化代理,已在setCapabilities中完成 }
额外注意事项
- 替换Thread.sleep:尽量用Selenium的显式等待(比如
WebDriverWait)等待页面元素加载或网络请求完成,避免固定等待时间导致的不稳定 - 开启代理调试日志:如果还是没捕获到请求,可以添加
proxy.setLogLevel(ch.qos.logback.classic.Level.DEBUG);查看代理是否接收到流量 - BrowserStack Local兼容性:确保
browserstack.local已正确启动,代理能捕获到本地到BrowserStack的流量 - 版本兼容:确认BrowserMob Proxy版本(2.1.5)和Selenium版本兼容,建议使用对应版本的依赖
内容的提问来源于stack exchange,提问作者Joshua Bell
相关产品推荐
相关产品推荐

