Appium Appium 框架中,是如何做延时处理的?

云飞凌风 · 2015年01月20日 · 最后由 汪汪 回复于 2015年06月10日 · 340 次阅读

经常在测试时会遇到网络情况不好的时候,而此时需要打开这个界面后,才能执行这个操作。
如果此时因为网络慢,而导致在执行当前操作时,该操作界面还没有来得及显示在屏幕上,该如何处理?

public boolean elementExist(String locator){
        boolean wait = false;
         try{
             wait = new WebDriverWait(driver, 5).until(new ExpectedCondition<Boolean>() {
                 public Boolean apply(WebDriver d) {
                     return d.findElement(By.name(locator)).isDisplayed();
                 }
             });
         }catch(Exception e){

         }
         return wait;
    }
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 6 条回复 时间 点赞

我看了一下 WebDriver 的 FluentWait。
简单而言,在制定时间内根据制定条件执行你需要的代码,知道代码为 true 或已超时。
你的代码翻译起来,就是 5 秒钟内找到 locator 的元素, 如果找到返回 true,不再查找;如果没找到,继续找,5 秒后抛出超时异常。

你要确定一下一些内容,进行排查

  1. App 的类型, Native?Hybrid?HTML5?(我猜测是 Hybrid 的,混合应用) 2.超时时间是否够用?
  2. 是否元素的显示是通过 isDisplay() 判断的,有的元素可能 isDisplay 为 false,但是仍然显示,我遇到过这个问题。
  3. locator 传递的是否正确?这也很正常,很容易马虎的。
  4. 程序的 bug?

附上 webDriverWait 的代码,很容易看懂的。

/**
 * Repeatedly applies this instance's input value to the given function until one of the following
 * occurs:
 * <ol>
 * <li>the function returns neither null nor false,</li>
 * <li>the function throws an unignored exception,</li>
 * <li>the timeout expires,
 * <li>
 * <li>the current thread is interrupted</li>
 * </ol>
 *
 * @param isTrue the parameter to pass to the {@link ExpectedCondition}
 * @param <V> The function's expected return type.
 * @return The functions' return value if the function returned something different
 *         from null or false before the timeout expired.
 * @throws TimeoutException If the timeout expires.
 */
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 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);
    }
  }
}

UI 自动化就这样...设置合理的等待/超时时间吧..

def waitForID(driver, idstr, msg, timeout = 15):
    return WebDriverWait(driver,timeout).until(lambda driver: driver.find_element_by_id(idstr).is_displayed(), msg)

我在 python 里是这么处理的。。。

#3 楼 @wang04170 问一下,你怎么 import 的,能看看完整的代码么

http://testerhome.com/topics/2576 我新写一篇,你可以看看

#4 楼 @mads
两个思路 一个是单独实现一个静态的方法来实现等待

from selenium.webdriver.support.wait import WebDriverWait

    @staticmethod
    def waitForID(driver, idstr, msg, timeout = 15):
        return WebDriverWait(driver,timeout).until(lambda driver: driver.find_element_by_id(idstr).is_displayed(), msg)

还有一个方法是自己定义一个 driver,继承 Appium 的 webdriver.Remote,在 driver 里扩展一些自定义的方法就可以了,后面就可以直接用这个 driver 类来获取对象和调用这个 wait 方法了

from appium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
class driver(webdriver.Remote):
......
    def waitForID(self, idstr, msg, timeout = 15):
        return WebDriverWait(self,timeout).until(lambda driver: driver.find_element_by_id(idstr).is_displayed(), msg)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册