我遇到了Java Selenium的问题。我用它来自动化测试网页,结构非常复杂 - 动态加载很多元素,html页面中有很多不必要的元素。让我的测试可靠是非常困难的。有时页面无法加载或我尝试点击尚不存在的按钮(当然用类似的方法)。
所以,我用这样的方法编写了Util类:
public static void findAndSendKeys(String vToSet, By vLocator) {
log.info("findAndSendKeys " + vLocator.toString());
int attempts = 0;
while (attempts < ATTEMPTS) {
WebElement element = null;
try {
element = webDriverWait.until(ExpectedConditions.presenceOfElementLocated(vLocator));
element.sendKeys(vToSet);
break;
} catch (TimeoutException e) {
log.error("timeOut exception " + e.getMessage());
} catch (StaleElementReferenceException e) {
log.error("StaleElementReference exception " + e.getMessage());
} catch (UnhandledAlertException e) {
log.error("UnhandledAlert exception " + e.getMessage());
Alert alert = driver.switchTo().alert();
alert.accept();
}
attempts++;
}
}
我知道它看起来很糟糕,我还没有对它进行重构,但是对于大多数情况,方法通常都能正常工作 - 在第二个或第三个循环输入字段上填充。
首先我只使用带有异常处理的sendKeys,但是我注意到虽然存在输入字段,但是抛出StaleElementReferenceException,所以我将while()放在这个静态方法中并尝试再次发送Keys。 有时我的webPage显示只是验证的警报,在捕获异常并忽略警报后,我可以继续工作。
我想知道..如果在Selenium IDE中存在类似于“Pause 1000”方法的方法,可能会更容易。有时我的网页工作得很快,很好,有时页面加载过程很长,我不得不等待。
while()循环也存在问题。我不知道如果while循环结束并且没有发送任何内容该怎么办 - 例如加载的页面/容器是空白的,动态加载失败,所以没有机会找到我们的输入字段
自动化此网页的测试过程让我头疼。请原谅,我没有技术支持,而且我独自一人。
答案 0 :(得分:0)
在我看来,你正试图过度设计整个事情。我认为你正在尝试编写一个能够处理所有情况的函数,我认为这不是一个好方法。每个案例都可能有所不同,您需要了解每个案例并妥善处理。
一些提示。
不要循环wait.until()
。而不是
for (int i = 0; i < 5; i++)
{
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(...);
}
DO
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until(...);
最终结果是相同的(最多50秒等待),但第二个代码不那么令人困惑。阅读等待以更好地理解它们。等待的默认行为是等待最长时间并每500ms轮询一次条件。
如果你得到StaleElementReferenceException
,你就会遗漏一些东西。我并不是说这听起来很关键......它发生了。你需要了解页面的HTML是如何变化的,因为你正在寻找一个正在消失的元素,而然后你试图抓住它。您需要更改要查找的元素或查找元素。
请勿使用Thread.sleep()
。一般来说,这是一种不好的做法,因为它是硬编码的。根据环境的不同,可能太长或等待时间不够长。而是更喜欢您已经使用的wait.until()
机制。有时,困难的部分是找到等待的东西。
如果您在项目排序后尝试抓取页面,则需要确定排序后的更改。也许列标题上有一个箭头,表示排序方向(升序与降序)?你可以做的一件事是抓住一个TD元素,等待它变得陈旧(当元素被分类时),然后重新调整所有元素?
也许是这样的
WebDriverWait wait = new WebDriverWait(driver, 10);
// grab the first TD as a stale reference
WebElement td = driver.findElement(By.tagName("td"));
// wait for it to go stale
wait.until(ExpectedConditions.stalenessOf(td));
// now grab them all and do something with them
List<WebElement> tds = driver.findElements(By.tagName("td"));
如果没有指向页面的链接或对页面上发生的事情和一些相关HTML的更多解释,我不确定我们还能提供什么。
答案 1 :(得分:0)
此代码适用于我:
jsPageLoadWait ="
try {
if (document.readyState !== 'complete') {
return false; // Page not loaded yet
}
if (window.jQuery) {
if (window.jQuery.active) {
return false;
} else if (window.jQuery.ajax && window.jQuery.ajax.active) {
return false;
} else if ($(':animated').length != 0) {
return false;
}
}
if (window.angular) {
if (!window.qa) {
// Used to track the render cycle finish after loading is complete
window.qa = {
doneRendering: false
};
}
// Get the angular injector for this app (change element if necessary)
var injector = window.angular.element('body').injector();
// Store providers to use for these checks
var $rootScope = injector.get('$rootScope');
var $http = injector.get('$http');
var $timeout = injector.get('$timeout');
// Check if digest
if ($rootScope.$$phase === '$apply' || $rootScope.$$phase === '$digest' || $http.pendingRequests.length !== 0) {
window.qa.doneRendering = false;
return false; // Angular digesting or loading data
}
if (!window.qa.doneRendering) {
// Set timeout to mark angular rendering as finished
$timeout(function() {
window.qa.doneRendering = true;
}, 0);
return false;
}
}
return true;
} catch (ex) {
return false;
}"
public static Boolean WaitLoad(this ISearchContext context, UInt32 timeoutInMilliseconds = 10000, UInt32 millisecondPolling = 1000)
{
Boolean waitReadyStateComplete;
var wait = new DefaultWait<ISearchContext>(context);
wait.Timeout = TimeSpan.FromMilliseconds(timeoutInMilliseconds);
wait.PollingInterval = TimeSpan.FromMilliseconds(millisecondPolling);
wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(StaleElementReferenceException));
waitReadyStateComplete = wait.Until<Boolean>(ctx =>
{
if ((Boolean)((IJavaScriptExecutor)context).ExecuteScript(jsPageLoadWait))
return true;
else
return false;
});
return waitReadyStateComplete;
}