我使用selenium webdriver来点击链接,但它会抛出NoSuchElementException。我正在使用xpath,当我在Inspect Element选项卡中的浏览器中执行搜索时找到所需的链接,当我在浏览器中执行以下javascript时 - 控制台,链接被优雅地点击,
Javascript代码:
var element = window.top.document.evaluate("//a[@id='clients']/i[@class='icon-chevron-down']" ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;if (element != null) { element.click(); } else { alert('Not Found'); }
但不确定为什么selenium会抛出以下异常,我在点击之前尝试过各种明确的等待。
org.openqa.selenium.NoSuchElementException: no such element
(Session info: chrome=42.0.2311.135)
(Driver info: chromedriver=2.9.248307,platform=Mac OS X 10.9.5 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 45.05 seconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: 'unknown', revision: 'unknown', time: 'unknown'
System info: host: 'VDO105.local', ip: '172.16.0.70', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.9.5', java.version: '1.7.0_75'
Session ID: b9f85e7103119d4c7b7ff265d02187ca
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities [{platform=MAC, acceptSslCerts=true, javascriptEnabled=true, browserName=chrome, chrome={userDataDir=/var/folders/1v/pyj3pk396pb0z71_tlqcppgh0000gn/T/.org.chromium.Chromium.TePZ9p}, rotatable=false, locationContextEnabled=true, version=42.0.2311.135, takesHeapSnapshot=true, cssSelectorsEnabled=true, databaseEnabled=false, handlesAlerts=true, browserConnectionEnabled=false, webStorageEnabled=true, nativeEvents=true, applicationCacheEnabled=false, takesScreenshot=true}]
以下是链接的HTML代码:
<a ng-show="sideBar.length" class="dropdown-toggle toggle-active" id="clients" href="javascript:void(0);">
<i class="icon-group"></i>
<span class="menu-lv-1 ng-binding">Clients</span>
<i class="icon-chevron-down"></i>
</a>
答案 0 :(得分:0)
当您的页面由javascripts填充时,通常会发生这种情况。当一个新页面出现后,selenium会在完成加载后收到。如果之后发生了变化,硒就不会有这些变化。
听起来这是你的问题。
为此我创建了特殊功能而不是selenium提供的功能。该类包含WebDriver实例。
public void click(final By by){
act(by, 3, new Callable<Boolean>() {
public Boolean call() {
wait.until(ExpectedConditions.refreshed(ExpectedConditions.visibilityOfElementLocated(by)));
driver.findElement(by).click();
logger.info("Button "+stripBy(by) + " clicked");
return Boolean.TRUE; // FOUND IT
}
});}
function act是一个特殊的函数,用于重试元素上的speficyfied操作。
private void act(By by, int tryLimit, boolean mode, Callable<Boolean> method){
logger.trace( "Looking for element: " + stripBy(by) );
driver.manage().timeouts().implicitlyWait( 5, TimeUnit.SECONDS );
boolean unfound = true;
int tries = 0;
while ( unfound && tries < tryLimit ) {
tries += 1;
try {
WebDriverWait wait = new WebDriverWait(driver, 500);
wait.until(ExpectedConditions.refreshed(ExpectedConditions.visibilityOfElementLocated(by)));
wait.until(ExpectedConditions.refreshed(ExpectedConditions.elementToBeClickable(by)));
unfound = !method.call(); // FOUND IT, this is negated since it feel more intuitive if the call method returns true for success
} catch ( StaleElementReferenceException ser ) {
logger.error( "ERROR: Stale element exception. " + stripBy(by));
unfound = true;
} catch ( NoSuchElementException nse ) {
logger.error( "ERROR: No such element exception. " + stripBy(by)+"\nError: "+nse );
unfound = true;
} catch ( Exception e ) {
logger.error( e.getMessage() );
}
}
driver.manage().timeouts().implicitlyWait( Constants.DEFAULT_IMPLICIT_WAIT, TimeUnit.SECONDS );
if(unfound)
Assert.assertTrue(false,"Failed to locate element by locator " + stripBy(by));}