所有测试自动化工具的问题在于,自动化工具执行时页面可能尚未完成加载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,并解决了我的问题。谢谢迈克。 –