1

Selenium2 が限られた時間のポーリング後に WebElement オブジェクトの取得に失敗した場合、JavascriptExecutor にフェイルオーバーするという考えがあります。ご覧のとおり、このメソッドには、getElementByLocator を呼び出すときに「フェイルオーバー」Javascript スニペットを事前定義する必要があるという制限があります。これを動的に行う方法は考えられませんでした。誰かがこれを改善するのを手伝ってくれるなら、それがどんなに小さくても、最良の提案への答えを授与します.

// failover example1: "document.getElementById('gbqfb')"
// failover example2: "document.querySelector("div#gbqfb")"
public static WebElement getElementByLocator(final By locator, String failover) {
  Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
    .withTimeout(30, TimeUnit.SECONDS)
    .pollingEvery(5, TimeUnit.SECONDS);
    .ignoring(NoSuchElementException.class,StaleElementReferenceException.class);
  WebElement we = wait.until( ExpectedConditions
      .presenceOfElementLocated( locator ) );
  if ( we.isNull() ) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    if ( !failover.isEmpty() ) {
      we = (WebElement)js.executeScript( failover );
      if ( we.isNull() ) LOG.info("Still couldn't get element.");
    } else {
      LOG.info("No failover String available.  Cannot try with " +
        "a JavascriptExecutor.");
    }    
  }
  return we;
}
4

1 に答える 1

0

実際にここで同様の質問に答えました

そのようなJavaScriptに何かを委譲することはお勧めしません.Seleniumが提供するものを使用してください..それで十分です.

これまでに構築したすべてのフレームワークに組み込んだもので、非常に効率的です。ここにあるフレームワークからの抜粋を次に示します

オブジェクトに対してアクションを実行する前に、一種の疑似待機タイプのメソッドを実装します。自分で試してみてください。とても効率的です。

これらはAutomationTestクラスのメソッドです

/**
 * Checks if the element is present or not.<br>
 * @param by
 * @return <i>this method is not meant to be used fluently.</i><br><br.
 * Returns <code>true</code> if the element is present. and <code>false</code> if it's not.
 */
public boolean isPresent(By by) {
    if (driver.findElements(by).size() > 0) return true;
    return false;
}

/**
 * Private method that acts as an arbiter of implicit timeouts of sorts.. sort of like a Wait For Ajax method.
 */
private WebElement waitForElement(By by) {
    int attempts = 0;
    int size = driver.findElements(by).size();

    while (size == 0) {
        size = driver.findElements(by).size();
        if (attempts == MAX_ATTEMPTS) fail(String.format("Could not find %s after %d seconds",
                                                         by.toString(),
                                                         MAX_ATTEMPTS));
        attempts++;
        try {
            Thread.sleep(1000); // sleep for 1 second.
        } catch (Exception x) {
            fail("Failed due to an exception during Thread.sleep!");
            x.printStackTrace();
        }
    }

    if (size > 0) System.err.println("WARN: There are more than 1 " + by.toString() + " 's!");

    return driver.findElement(by);
}

私がしていることは、いつでも何かを実行することです。

getText(By.cssSelector("input#someId"))

最初に見つからない場合は、1 秒間待機します。見つかった場合は続行します。その後 5 回実行するため、合計 5 秒間待機します。必要な要素が見つからない場合は、その時点でテストが事実上失敗するため、まったく問題ありません。

driver.findElements()また、経験上、それらよりも使用した方が効果的であると言えますWebDriverWait

それは私がそれらを使用しないという意味ではありません.. そのためではありません. 残念ながら、私はこの機能を Selenium フレームワークの開始に追加していませんでした。そのため、いつ Webdriverwait を使用したかを説明します。

だから私のテストは次のようになります -

@Config(url="http://systemunder.test", browser=CHROME)
public class MyClass extends AutomationTest {

    @Test
    public void testSomething() {
        setText(By.id("blah")) // if <* id="blah" /> doesn't exist, waits 1+ seconds for it to appear before interacting.
        .click(By.id("Blah2")) // ^ same thing here.
        .waitForPresent(By.cssSelector("ajaxy")); // this method right here would circumvent the hard waits, with webdriverwait's.
    }
}

以前はうまくいかなかった理由を正確には覚えていませんが、そのようなもので webdriverwaits を使用することは完璧です。

于 2013-10-10T03:24:20.173 に答える