Selendroid 里面有一个坑,比如下面的代码:

@Test
public void shouldGetBodyDOMElementViaJavascript() {
  openWebdriverTestPage(HtmlTestData.XHTML_TEST_PAGE);
  WebElement bodyByJS = (WebElement) driver().executeScript("return document.body;");
  Assert.assertEquals("body", bodyByJS.getTagName());
}

这段代码的意思是,我执行一个 javascript 脚本 return document.body,按照 JavascriptExecutor 的 API 来看,这边就是返回了一个 WebElement 了 。

<li>For an HTML element, this method returns a WebElement</li>
   * <li>For a decimal, a Double is returned</li>
   * <li>For a non-decimal number, a Long is returned</li>
   * <li>For a boolean, a Boolean is returned</li>
   * <li>For all other cases, a String is returned.</li>
   * <li>For an array, return a List&lt;Object&gt; with each object following the rules above. We
   * support nested lists.</li>
   * <li>Unless the value is null or there is no return value, in which null is returned</li>

然后呢,拿到这个 WebElement 后,如果对它进行一些操作,这个时候你就要小心了。比如 getTagName 这个方法,他就会通过 http 请求路由到 SafeRequestHandler 的实现 GetElementTagName 里面,

public class GetElementTagName extends SafeRequestHandler {

  public GetElementTagName(String mappedUri) {
    super(mappedUri);
  }

  @Override
  public Response safeHandle(HttpRequest request) throws JSONException {
    SelendroidLogger.info("get tag name of element command");
    String id = getElementId(request);
    AndroidElement element = getElementFromCache(request, id);
    return new SelendroidResponse(getSessionId(request), element.getTagName());
  }
}

这里面就会去之前缓存的 Element 里面取,结果这坑爹货是 webview 里面的 executeScript 的 Element 并没有缓存,于是你就会得到下面的异常:

org.openqa.selenium.StaleElementReferenceException: The element with id ':wdc:1433853394939' was not found.

这个方法其实是他没用设计好。比如 getPageTitle 就好很多。

public class GetPageTitle extends SafeRequestHandler {

  public GetPageTitle(String mappedUri) {
    super(mappedUri);
  }

  @Override
  public Response safeHandle(HttpRequest request) throws JSONException {
    SelendroidDriver driver = getSelendroidDriver(request);
    return new SelendroidResponse(getSessionId(request), driver.getTitle());
  }
}

直接去 SelendroidDriver 里拿,

@Override
public String getTitle() {
  if (isNativeWindowMode()) {
    return selendroidNativeDriver.getTitle();
  } else {
    return selendroidWebDriver.getTitle();
  }
}


↙↙↙阅读原文可查看相关链接,并与作者交流