Java Selenium测试benchmark方法统计页面加载耗时异常问题
核心原因
你遇到的问题和线程无关,是Java方法参数的求值顺序导致的:
- Java调用方法时会先计算所有传入参数的值,再把值传递给方法。你调用
subTestDelay的时候,会先执行expectedPageIsLoaded方法完成页面等待、得到布尔类型的返回值,再把这个布尔值作为condition参数传入subTestDelay。 - 你传给
benchmark方法的Runnable内部,仅做了「判断已经提前算好的布尔值是否为假」的操作,这个操作本身耗时不到1毫秒,自然统计出来的前后时间戳完全一致。 - 真正的页面加载等待逻辑在进入
benchmark方法之前就已经执行完毕,根本没有被纳入耗时统计范围。
解决方案
方案1:修改参数为延迟求值的Supplier(推荐)
把subTestDelay的condition参数从boolean改为Supplier<Boolean>,让页面等待逻辑放到Runnable内部执行,被纳入耗时统计:
// 修改subTestDelay的参数类型 public static void subTestDelay(boolean log, Supplier<Boolean> conditionSupplier, int delay, String message) { if (log) { SoftAssert softAssert = new SoftAssert(); ExtentTestManager.benchmark(() -> { // 这里才真正执行页面等待逻辑,会被统计耗时 boolean condition = conditionSupplier.get(); if (!condition) { tempData.failStatus(); softAssert.fail("Timeout after waiting ".concat(String.valueOf(delay)).concat(" seconds for ").concat(message)); } }); softAssert.assertAll(); } else { Assert.assertTrue(conditionSupplier.get(), "Timeout after waiting ".concat(String.valueOf(delay)).concat(" seconds for ").concat(message)); } }
调用subTestDelay时,把原来直接传入expectedPageIsLoaded(...)的写法,改成包装为Supplier传入:
// 原来的调用写法(提前执行了等待逻辑) // subTestDelay(true, expectedPageIsLoaded(driver, 180, "user authentication"), 180, "user authentication load"); // 修改后的调用写法(把逻辑封装成Supplier,延迟执行) subTestDelay(true, () -> expectedPageIsLoaded(driver, 180, "user authentication"), 180, "user authentication load");
方案2:直接把等待逻辑移到benchmark的Runnable内
如果不想修改subTestDelay的参数定义,也可以直接调整代码结构,把expectedPageIsLoaded的调用放到Runnable内部,确保被统计到。
额外优化建议
统计代码段耗时不要用LocalDateTime,它是民用挂钟时间,会受系统时间校准、时区调整等因素影响,统计误差大。推荐用System.nanoTime()或者Instant.now()做耗时统计,精度和稳定性更高。
内容的提问来源于stack exchange,提问作者Mattemingda
相关产品推荐
相关产品推荐

