2013-10-10 21 views
1

如果Selenium2在有限的時間內輪詢後未能檢索到WebElement對象,我有這個想法用於故障切換到JavascriptExecutor。如您所見,該方法具有限制,即在調用getElementByLocator時需要預先定義「故障轉移」JavaScript代碼段。我想不出有什麼辦法來動態地做到這一點。如果任何人都可以幫助我改進這一點,我會將答案提供給最好的建議,儘管它很小。當Selenium2 findElement失敗時,故障轉移到JavascriptExecutor?

// 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; 
} 

回答

0

其實回答過類似的問題here

我不會建議委託什麼樣的..使用JavaScript什麼硒給你..這是非常充足的。

東西,我把它放在每一個我曾經構建的框架,這是非常有效的..這是從框架exerpt發現here

在我對對象執行任何操作之前,我實現了一種僞等待類型的方法。親自嘗試一下。這非常有效。

這些都是從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,完美無瑕。

+0

我很感激長答案和非常詳細的信息。我的問題的目的是捕捉罕見的邊緣情況,根據我的經驗,有時在從一個版本的Selenium2升級到另一個版本後會發生這種情況,在這種情況下,有時候一個Element不能被常規腳本檢索,並且我試圖避免小編輯在那些需要JavascriptExecutor才能訪問的情況下。因此,試圖提出一種工作故障轉移方法。正如你從我的代碼中看到的,99%的時間,它不會調用JavascriptExecutor。故障轉移僅適用於邊緣情況。 – djangofan

+0

作爲一名測試工程師,我從未在我的日子裏遇到過這種類型的問題,但沒有使用上面提供的內容進行糾正。你說這個元素「不再可以被普通腳本檢索」。這是什麼意思?你提供了一個選擇器來選擇對象,並且你很好去.. – sircapsalot

+0

那麼,我說我的平常代碼工作超過99%的時間,我使用類似於你的方法,但也許稍微更現代化(自我使用FluentWait,ExpectedConditions,LoadableComponent等等。),但我也說根據我的經驗,.findElement()通常不是100%完全可靠的。我想提出一些我可以說的堅定的東西。編寫框架時,這是框架用戶的目標。此外,沒有理由認爲.findElement將是100%,因爲加載DOM不是100%,也不是瞬間... – djangofan