selenium 用隐式等待 还是 用 显示等待

隐式等待 vs 显示等待

隐式等待显示等待
全局声明,代码简洁局部声明,代码复杂冗余
等待发生在webDriver控制浏览器时,不可控,仅适用于获取元素等待发生在本地编写的代码逻辑,可以自定义等待获取条件
仅支持获取元素,找不到超时也可以判断等待元素消失
返回结果是元素或超时异常返回结果可以自定义

代码对比

/**
*隐式等待
*/
WebDriver driver = new FirefoxDriver();
//声明一次 告诉webDiver 获取元素时 最大等待时间10s
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://blog.csdn.net/zkf9044");
WebElement myDynamicElement = driver.findElement(By.id("uid"));

/**
*显示等待
*/
WebDriver driver = new FirefoxDriver();
driver.get("https://blog.csdn.net/zkf9044");
//创建一个等待对象,通过等待对象去执行的获取元素都是等待10秒
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement myDynamicElement = wait.until(
  ExpectedConditions.presenceOfElementLocated(By.id("uid"))//内置预期等待条件
  );

以下是内置预期条件的API:https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

自定义显示等待 预期条件

如果你不知道该怎么写,可以看看内置预期条件源码ExpectedConditions.presenceOfElementLocated(By.id("uid")) 源码很简单,阅读起来毫无压力

 public static ExpectedCondition<WebElement> presenceOfElementLocated(
      final By locator) {
    return new ExpectedCondition<WebElement>() {
      @Override
      public WebElement apply(WebDriver driver) {
        return findElement(locator, driver);
      }

      @Override
      public String toString() {
        return "presence of element located by: " + locator;
      }
    };
  }

再看wait.until(ExpectedConditions.presenceOfElementLocated(By.id("uid")));
until方法的源码,他会执行Function 类 的 apply()方法,ExpectedConditionFunction的子类;

继续分析 执行apply(),如果返回值不为空,本且是boolean类型时,返回结果为true则返回结果,否则睡眠0.5秒后再检查,如果等待的时间超过设置的最大等待时间则抛出异常timeoutException

public <V> V until(Function<? super T, V> isTrue) {
    long end = clock.laterBy(timeout.in(MILLISECONDS));
    Throwable lastException = null;
    while (true) {
      try {
        V value = isTrue.apply(input);
        if (value != null && Boolean.class.equals(value.getClass())) {
          if (Boolean.TRUE.equals(value)) {
            return value;
          }
        } else if (value != null) {
          return value;
        }
      } catch (Throwable e) {
        lastException = propagateIfNotIngored(e);
      }

      // Check the timeout after evaluating the function to ensure conditions
      // with a zero timeout can succeed.
      if (!clock.isNowBefore(end)) {
        String message = messageSupplier != null ?
            messageSupplier.get() : null;

        String toAppend = message == null ?
            " waiting for " + isTrue.toString() : ": " + message;

        String timeoutMessage = String.format("Timed out after %d seconds%s",
            timeout.in(SECONDS), toAppend);
        throw timeoutException(timeoutMessage, lastException);
      }

      try {
        sleeper.sleep(interval);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new WebDriverException(e);
      }
    }
  }

根据源码分析可知,我们需要实现ExpectedCondition 接口重写apply

//预期条件 这个按钮没有被禁用
private static ExpectedCondition<WebElement> elementToBeClickable(
		      final By locator) {
		      //实现ExpectedCondition接口 返回 WebElement
		    return new ExpectedCondition<WebElement>() {

		      public ExpectedCondition<WebElement> visibilityOfElementLocated =
		          ExpectedConditions.visibilityOfElementLocated(locator);

		      @Override
		      public WebElement apply(WebDriver driver) {
		      		//嵌套使用 检查元素是否可见 调用apply()
		        WebElement element = visibilityOfElementLocated.apply(driver);
		        try {
		        	 String isDisabled=element.getAttribute("disabled");
		          if (element != null && element.isEnabled() && StringUtils.isEmpty(isDisabled)) {					
		          	//element 不会空返回元素  否则返回null继续等待
		            return element;
		          } else {
		            return null;
		          }
		        } catch (Throwable e) {
		          return null;
		        }
		      }

		      @Override
		      public String toString() {
		        return "element to be clickable: " + locator;
		      }
		    };
		  }


//使用的时候
//我需要获取的按钮是没有被禁用的,才可点击
WebElement element= wait.until(elementToBeClickable(By.id("btn")));
element.click();

总结

使用显示等待最好,好的的东西除了“贵” 啥都好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值