2016-03-02 89 views
0

我使用Selenium的v2.52和WebDriver与C#。我想实现的目标应该相当简单,但我无法找到解决方案:我想通过多个By-criteria找到一个元素。找到一个满足多个By-criteria的Selenium Webdriver元素

比方说,我有这样的事情:

<a href="#" class="foo">Click me!</a> 
<a href="#" class="bar">Click me!</a> 
<p class="foo">Click me!</p> 

忽略了一个事实,我可以使用By.CssSelectorBy.CssSelectorBy.XPath等。我假定它应该可以做这样的事情:

driver.FindElement(By.TagName("a").ClassName("foo")) 
// ...or something like this... 
driver.FindElement(By.TagName("a"), By.ClassName("foo")) 

OpenQA.Selenium.Support.PageObjects.ByChained不会做的伎俩,因为它是搜索层次。

有没有办法找到符合多个By-criteria的元素?

最好的问候, 卡斯滕

+0

,什么是错用'XPath'和'CssSelector'? – Andersson

+0

它没有什么不对。好的,也许XPath有点静态。我只是想知道我是否可以像我描述的那样找到元素。 –

+0

我想没有这样的方式来找到多个过滤器的元素。无论如何,'xpath'会更加灵活,因为只有'xpath'和'cssSelector'才能找到许多'HTML'属性。还要注意,包含空格的类名不能与By.ClassName(“foo”)方法匹配,但可以与By.XPath('// * [@ class =“foo”]匹配')'... – Andersson

回答

0

我想象这样的事情可能是你的工作情况。

public IWebElement FindElementByMultipleCriteria(List<By> Criteria, IReadOnlyCollection<IWebElement> toFilter = null) 
{ 
    // If we've reached the end of the criteria list, return the first element: 
    if (Criteria.Count == 0 && toFilter != null) return toFilter.ElementAt(0); 

    // Take the head of the criteria list 
    By currentCriteria = Criteria[0]; 
    Criteria.RemoveAt(0); 

    // If no list of elements found exists, we get all elements from the current criteria: 
    if (toFilter == null) 
    { 
     toFilter = Driver.FindElements(currentCriteria); 
    } 
    // If a list does exist, we must filter out the ones that aren't found by the current criteria: 
    else 
    { 
     List<IWebElement> newFilter = new List<IWebElement>(); 
     foreach(IWebElement e in Driver.FindElements(currentCriteria)) 
     { 
      if (toFilter.Contains(e)) newFilter.Add(e); 
     } 
     toFilter = newFilter.AsReadOnly(); 
    } 

    // Pass in the refined criteria and list of elements found. 
    return FindElementByMultipleCriteria(Criteria, toFilter); 
} 

IWebElement example = FindElementByMultipleCriteria(new List<By>(){ By.TagName("a"), ClassName("foo") }); 

从本质上讲,你正在做在通过第一By发现元素的列表你然后通过其余的By标准并从该初始列表中移除永远不会再次找到的元素。

这是非常低效的,我不明白你为什么想要这样做,但它是存在的。

哦另外,您需要添加using System.Linq;才能与IReadOnlyCollection互动。

+0

的确,这听起来像一个可怕的想法。 ;)如果开箱后没有支持,那就罚款。我想知道是否有可用的东西,但显然不是。 –

+0

我想它不存在,因为你可以给它一个像[By.TagName(“a”),By.TagName(“input”),By.TagName(“h1”)]'和只是砖你的程序,哈哈 –

0

嗯,我想你可以尝试这样的事情,让我知道,如果它的工作原理:

public IWebElement FindElementUsingNestedBy(By firstCriteria, By secondCriteria) 
    { 
     var allElements = Driver.FindElements(firstCriteria); 
     foreach (var webElement in allElements) 
     { 
      try 
      { 
       var desiredObject = webElement.FindElement(secondCriteria); 
       return desiredObject; 
      } 
      catch (NotFoundException ex) 
      { 

      } 
     } 
     return null; 
    } 
+0

如果我没有错,这不是我所期待的。您的'secondCriteria'正在从firstCriteria中搜索那些元素下面的元素(从DOM的角度来看)。这个功能已经被'ByChained'覆盖。我希望所有标准都匹配一个元素。 –

相关问题