如何检查元素是否存在?

问题描述 投票:0回答:9

在我使用 Firefox Selenium WebDriver 的 C# Windows Forms 应用程序中,我需要检查某个元素是否存在,如果不存在,请单击另一个元素。如果有视频,看完就变成W_VIEWED

:

driver.FindElement(By.XPath("//div[@class='video']/a")).Click(); else { driver.FindElement(By.XPath("//div[@class='W_VIEWED']/a")).Click(); }

错误 3 只有赋值、调用、递增、递减、await 和 new 对象表达式可以用作语句 242

c# selenium firefox xpath
9个回答
53
投票
您可以使用以下方法检查元素是否存在

bool isElementDisplayed = driver.findElement(By.xpath("element")).isDisplayed()
记住,

findElement

如果没有找到元素就会抛出异常,所以你需要正确处理它。

在我的一个应用程序中,我通过检查单独函数中的元素来处理异常:

private bool IsElementPresent(By by) { try { driver.FindElement(by); return true; } catch (NoSuchElementException) { return false; } }
通话功能:

if (IsElementPresent(By.Id("element name"))) { // Do if exists } else { // Do if does not exists }
    

33
投票
您可以使用带有“s”的 FindElements 来确定它是否存在,因为 FindElement 会导致异常。 如果 FindElements 不返回元素,则返回一个空列表。

List<IWebElement> elementList = new List<IWebElement>(); elementList.AddRange(driver.FindElements(By.XPath("//input[@att='something']"))); if(elementList.Count > 0) { //If the count is greater than 0 your element exists. elementList[0].Click(); }
    

13
投票
所以我最近想出了另一种方法,它

更快。如果您的元素具有唯一 ID 或页面其他位置不存在的某些属性,您可以检查 PageSource。

driver.PageSource.Contains("UniqueID");
它检查页面以查看 ID 或其他唯一文本是否存在。  这几乎是瞬间发生的,而不是使用 Try/Catch 语句,后者大约需要 20 秒。  FindElements 也需要很长时间才能运行。


0
投票
我使用了接受的答案的解决方案一段时间,但我需要一种更快的方法来检查,而不是每次检查失败时都等待超时。因此,我制作了一些适用于 IWebElement 和 IWebDriver 的扩展函数,用于检查标签或类是否存在。

public static class ExtensionMethods { public static bool ContainsTag(this IWebElement element, string tagName) { string elementText = element.GetAttribute("innerHTML"); return CheckStringForTag(elementText, tagName); } public static bool ContainsClass(this IWebElement element, string className) { string elementText = element.GetAttribute("innerHTML"); return CheckStringForClass(elementText, className); } public static bool ContainsTag(this IWebDriver driver, string tagName) { return CheckStringForTag(driver.PageSource, tagName); } public static bool ContainsClass(this IWebDriver driver, string className) { return CheckStringForClass(driver.PageSource, className); } private static bool CheckStringForTag(string text, string tagName) { if (!string.IsNullOrWhiteSpace(text)) { return text.Contains("<" + tagName + ">") || text.Contains("</" + tagName + ">") || text.Contains("<" + tagName + " "); } return false; } private static bool CheckStringForClass(string text, string className) { if (!string.IsNullOrWhiteSpace(text)) { string pattern = string.Format(".*class[\\s]?=[\\s]?.*[\\s'\"]{0}[\\s'\"].*.*", className); Match m = Regex.Match(text, className, RegexOptions.IgnoreCase); return m.Success; } return false; } public static string InnerHTML(this IWebElement element) { return element.GetAttribute("innerHTML"); } }
注意:这与 

Dominic Giallombardo 的答案类似,但对其进行了扩展。


0
投票
此方法将允许您等待元素存在。这对于有条件创建元素的前端

SPA 框架(例如 Vue.js)尤其重要。您可以根据应用程序的性能调整重试次数。无论如何,它都会等待您的 ELEMENT_FIND_WAIT_TIME * ELEMENT_FIND_WAIT_RETRY_COUNT

 毫秒,然后才会完全失败。这解决了我们遇到的问题。

protected Func<IWebElement> GetLazyElement(By by, int retryCount=0) { if (retryCount >= ELEMENT_FIND_WAIT_RETRY_COUNT) { throw new Exception("Wait timeout for element to show up" + by.ToString()); } return new Func<IWebElement>(() => { try { Debug.WriteLine("Finding element " + by.ToString()); var element = _webDriver.FindElement(by); return element; } catch (Exception) { Debug.WriteLine($"Failed to find element: {by} (Waiting {ELEMENT_FIND_WAIT_TIME}ms)"); Thread.Sleep(ELEMENT_FIND_WAIT_TIME); var lazyFunc = GetLazyElement(by, retryCount++); return lazyFunc(); } }); }
    

0
投票

多米尼克·吉隆巴尔多的回答对我有用。对于在后台加载的基于Ajax的信息,等待元素出现是必需的循环。

因此,如果您想在元素出现时等待并执行操作,可以使用标签和

go to label + else 条件。这是修改后的代码,它将通过循环等待元素出现:

检查某些元素

List<IWebElement> elementList = new List<IWebElement>(); elementList.AddRange(driver.FindElements(By.XPath("//div[@class='video']/a"))); if (elementList.Count > 0) { elementList[0].Click(); } else { System.Threading.Thread.Sleep(2000); goto checksomeelement; }
    

0
投票
我用的就是这个。 “verify”方法将根据元素是否存在返回 true 或 false。名为“testfunc”的方法是您输入元素名称的地方。在这个例子中,我想看看页面上是否显示“English”。

此外,我注意到在之前的帖子的评论中,人们说他们必须等待 10 秒或更长时间才能捕获。尝试删除代码中的显式等待以使 catch 立即起作用。

static public bool verify(string elementName) { try { bool isElementDisplayed = driver.FindElement(By.XPath(elementName)).Displayed; return true; } catch { return false; } return false; } static void testfunc() { bool test = verify("//option[contains(.,'English')]"); Console.WriteLine(test); }
    

0
投票
如果您正在使用

ImplicitWait

 并且想立即使用 
FindElement
 查看某个元素是否存在,请尝试以下代码:

ElementExists(By.Id(id)); static public bool ElementExists(By method) { var oldTime = _driver.Manage().Timeouts().ImplicitWait; _driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(1); try { bool isElementDisplayed = _driver.FindElement(method).Displayed; _driver.Manage().Timeouts().ImplicitWait = oldTime; return true; } catch { _driver.Manage().Timeouts().ImplicitWait = oldTime; return false; } }
    

0
投票
最佳实践(避免 try/catch)是使用

FindElements().Count

 函数(注意元素的“s”)。
如果元素不存在,则计数为
0
,否则元素存在

if(driver.FindElements(By.XPath("//div[@class='video']/a")).Count > 0) {...}


使用

FindElement().Displayed

 bool 的问题是,如果元素不存在,它会抛出异常。
如果您希望有类似的 bool 元素,您可以使用三元运算符来处理两种存在情况:

bool Displayed = driver.FindElements(By.XPath("//div[@class='video']/a")).Count > 0 ? true : false;


    

© www.soinside.com 2019 - 2024. All rights reserved.