所有測試自動化工具的問題在於,自動化工具執行時頁面可能尚未完成加載DOM。有各種各樣的複雜程度可以用來使其100%可靠。第一道防線是使用ExpectedConditions。因此,對於你的第一個例子,
WebDriver webDrive = ... // You have to initialize to a browser instance and navigate to your web page
By bySenderPostCode = By.name("sender-postCode");
Wait<WebDriver> wait_element = new WebDriverWait(webDriver, 40); // Wait up to 40 seconds
WebElement senderPostalCodeElement = wait_element.until(ExpectedConditions.visibilityOfElementLocated(bySenderPostCode));
senderPostalCodeElement.sendKeys("02791");
有很多執行JavaScript的複雜頁面可能會很痛苦。我用我寫了等待angularJs完成執行程序,等待裝載微調來完成,最後進行頁面的readyState等於完成:
waitForAngularToLoad(webDriver, 40);
wait_element.until((WebDriver dr1) -> (webDriver.findElement(mySpinner).getAttribute("class").contains("ng-hide")));
waitForBrowserReadystateComplete(webDriver);
這些必須進行調整的環境,您必須在其中運行。等待jQuery完成與等待AngularJs不同。但是我給你的東西應該讓你去。讓我知道結果如何。
編輯
我意識到,告訴你關於我的程序,我用它來等待,但不共享代碼是毫無意義的。加載微調器完全依賴於實現。沒有一種方法可以保證在任何地方都能正常工作,但我給了你AngularJs實現常見的一般形式。
這裏是別人:
public void waitForBrowserReadystateComplete(WebDriver webDriver) {
for (int a=0; a<20; a++) {
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver;
if (javascriptExecutor.executeScript("return document.readyState")
.toString().equals("complete")) {
break;
}
sleepResponsibly(500);
}
}
public void sleepResponsibly(int timeMillisecond){
try{
Thread.sleep(timeMillisecond);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
}
public boolean waitForAngularToLoad(WebDriver driver, int timeout) {
driver.manage().timeouts().setScriptTimeout(timeout, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver, timeout, 500L);
return wait.until(angularHasFinishedProcessing());
}
public static ExpectedCondition<Boolean> angularHasFinishedProcessing() {
return new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" +
"var el = document.querySelector('html');\n" +
"if (!window.angular) {\n" +
" callback('false')\n" +
"}\n" +
"if (angular.getTestability) {\n" +
" angular.getTestability(el).whenStable(function(){callback('true')});\n" +
"} else {\n" +
" if (!angular.element(el).injector()) {\n" +
" callback('false')\n" +
" }\n" +
" var browser = angular.element(el).injector().get('$browser');\n" +
" browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" +
"}";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString();
return Boolean.valueOf(isProcessingFinished);
}
};
}
請記住,如果你的系統在測試使用AngularJs內置角的人只工作。
EDIT 2查找元素
我使用谷歌Chrome瀏覽 「找到」 的元素。在Chrome中打開您的網頁。右鍵單擊顯示的元素。選擇檢查 - >複製 - >複製選擇器|複製Xpath。您也可以在Firefox下執行此操作。 Chrome只是習慣的力量。
EDIT3
jQuery的
public boolean waitForJquery(WebDriver driver, int timeout) {
return waitFor(driver, "return jQuery.active;", "0", timeout);
}
public boolean waitFor(WebDriver driver, final String javascriptString, final String targetString, int timeout) {
WebDriverWait wait = new WebDriverWait(driver, timeout, 500L);
/*
* If you are curious about what follows see:
\ * http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedCondition.html
*
* We are creating an anonymous class that inherits from ExpectedCondition and then implements interface
* method apply(...)
*/
ExpectedCondition<Boolean> isLoaded = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
String jsReturnedValue = "";
try {
jsReturnedValue = String.valueOf(((JavascriptExecutor)driver).executeScript(javascriptString));
return (jsReturnedValue.equals(targetString));
} catch (Exception e) {
log.info("Looking for: " + javascriptString + ", e.message: " + e.getMessage());
return true; // If Javascript not found then don't wait for it
}
}
}; // Terminates statement started by ExpectedCondition<Boolean> isLoaded = ...
return wait.until(isLoaded);
}
而只是爲了詳談,阿賈克斯
public boolean waitForPrototypeAjax(WebDriver driver, int timeout) {
return waitFor(driver, "return Ajax.activeRequestCount;", "0", timeout);
}
邁克你好,我知道應用程序使用jQuery不AngularJs。所以我用你的第一個例子。它沒有工作。你打開了我附加的鏈接嗎?當你點擊輻射按鈕時,你會看到窗體。我改變了'等待 wait_element = new WebDriverWait(webDriver,40);'等待 wait_element = new WebDriverWait(driver,40)';因爲它被標記(webDriver無法解析爲變量) –
您能更具體地瞭解「沒有工作」嗎?另外,請發佈您執行的更新後的代碼。請注意,[木偶和geckodriver功能尚未完成。這意味着它尚未完全符合WebDriver標準或與Selenium完全兼容。](https://github.com/mozilla/geckodriver)。所以我使用了selenium-java v2.53.1和firefox v47.0。 – MikeJRamsey56
我已經切換到chrome webdriver和selenium-java v2.53,並解決了我的問題。謝謝邁克。 –