Selenium FindElement函数的通用方法

时间:2017-04-13 21:03:26

标签: c# selenium

所以我创建了这个通用的find元素函数:

    public static IWebElement FindElement(IWebDriver driver, Func<IWebDriver, IWebElement> expectedCondtions, int timeoutInSeconds)
    {
        WebDriverWait webDriverWait = CreateWebDriverWait(driver, finder,timeoutInSeconds);
        webDriverWait.IgnoreExceptionTypes(typeof(NoSuchElementException));
        return webDriverWait.Until(expectedCondtions);
    }

    public static ReadOnlyCollection<IWebElement> FindElements(IWebDriver driver, Func<IWebDriver, ReadOnlyCollection<IWebElement>> expectedCondtions, int timeoutInSeconds)
    {           
        WebDriverWait webDriverWait = CreateWebDriverWait(driver, finder, timeoutInSeconds);
        webDriverWait.IgnoreExceptionTypes(typeof(NoSuchElementException));            
        return webDriverWait.Until(expectedCondtions);
    } 

    private static WebDriverWait CreateWebDriverWait(IWebDriver driver, IWebElement finder, int timeoutInSeconds)
    {
        WebDriverWait webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
        webDriverWait.IgnoreExceptionTypes(typeof(NoSuchElementException));
        return webDriverWait;
    }

用法:

        IWebElement element=
            WaitAndFindElement(
            driver,
            ExpectedConditions.ElementIsVisible(By.CssSelector("...")),
            120);

现在我想添加一个选项来查找element也不使用driver。 例如,我想要从另一个driver.FindElement搜索元素而不是element

IWebElemen element = ...
element.FindElement...

所以我想改变我的功能签名:

IWebElement FindElement(IWebDriver driver,Func<IWebDriver, IWebElement> expectedCondtions, int timeoutInSeconds)

要:

IWebElement FindElement(IWebDriver driver, IWebElement finder, Func<IWebDriver, IWebElement> expectedCondtions, int timeoutInSeconds)

如果finder为空,我想使用driver.FindElement进行搜索。 否则:finder.FindElement

所以我的问题是如何实现这一目标?

4 个答案:

答案 0 :(得分:0)

这很好:我在工作中有类似的案例,这就是我在C#中所做的:

IWebElement FindElement(IWebDriver driver, Func<IWebDriver, IWebElement> expectedCondtions, int timeoutInSeconds, IWebElement finder = null)

这意味着&#34; finder&#34;的默认值为null,您可以在指定或不指定函数的情况下调用函数。 (您可以将此参数的默认值添加到所有方法中)

然后,您可以在函数中简单地执行一个简单的if语句来确定如何查找元素。

if(finder != null)
{
    //use finder instead of driver and return
}
//Otherwise use driver

答案 1 :(得分:0)

如果您想让它变得通用,我认为您不需要使其复杂化。 这是解决问题的代码

Class WebElementFinder
{
 private static IWebElement FindElement(ISearchContext sc, By locator, int timeOutInceconds = 20)
        {
            DefaultWait<ISearchContext> wait = new DefaultWait<ISearchContext>(sc);
            wait.Timeout = TimeSpan.FromSeconds(timeOutInceconds);
            wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
            return wait.Until(x => GetElement(x, locator));
        }

        private static IWebElement GetElement(ISearchContext sc, By locator)
        {
           return sc.FindElement(locator);
        }
}

让我解释一下这部分代码,它将帮助您理解您提到的代码的问题。

  1. 如果您使用webdriver等待它从DefaultWait类驱动,它将IWebDriver转换为泛型类型。因此,直到使用驱动程序对象的方法才会有限制。
  2. 如果在方法中使用Func,则每个调用方法都需要为find元素创建函数。但是,您可以将其用作可选参数。
  3. 现在回到我的代码片段。 我使用了可以用于WebDriver和IWebElement的DefaultWait。两者都是从ISearchContext驱动的。 Locator将帮助您按照帖子中的要求在驱动程序/ IWebElement对象上查找Web元素

答案 2 :(得分:0)

Class WebElementFinder
{
   public static IWebElement FindElement(ISearchContext sc, By locator, Func<IWebElement, bool> elementCondition = null, int timeOutInceconds = 20)
        {
            DefaultWait<ISearchContext> wait = new DefaultWait<ISearchContext>(sc);
            wait.Timeout = TimeSpan.FromSeconds(timeOutInceconds);
            wait.PollingInterval = TimeSpan.FromSeconds(3);
            wait.IgnoreExceptionTypes(typeof(NoSuchElementException));

            return  wait.Until(x => GetElement(x, locator, elementCondition));
        }

        private static IWebElement GetElement(ISearchContext sc, By locator, Func<IWebElement, bool> elementCondition = null)
        {
             IWebElement webElement = sc.FindElement(locator);
             if(elementCondition != null)
            {
                if (elementCondition(webElement))
                    return webElement;
                else
                    return null;
            }
             else
            {
                return webElement;
            }
        }
}

用法:

 Func<IWebElement, bool> isElementVisible = (webElement) => webElement.Displayed;
            var element = FindElement(driver, By.Id("name_10"), isElementVisible);

答案 3 :(得分:0)

我尝试用这种方式编写,并且运行正常。可能不是最好的方法,但可以帮上忙,因为它对我有用。

public enum HtmlAttribute
    {
        ClassName,
        CssSelector,
        Id,
        LinkText,
        Name,
        TagName,
        XPath
    }
    public IWebElement FindWebELement(HtmlAttribute htmlAttribute, string attributeValue)
    {
        for (int i = 0; i < 20; i++)
        {
            switch (htmlAttribute)
            {
                case HtmlAttribute.ClassName:
                    webElement = Driver.FindElement(By.ClassName(attributeValue));
                    break;
                case HtmlAttribute.CssSelector:
                    webElement = Driver.FindElement(By.CssSelector(attributeValue));
                    break;
                case HtmlAttribute.Id:
                    webElement = Driver.FindElement(By.Id(attributeValue));
                    break;
                case HtmlAttribute.LinkText:
                    webElement = Driver.FindElement(By.LinkText(attributeValue));
                    break;
                case HtmlAttribute.Name:
                    webElement = Driver.FindElement(By.Name(attributeValue));
                    break;
                case HtmlAttribute.TagName:
                    webElement = Driver.FindElement(By.TagName(attributeValue));
                    break;
                case HtmlAttribute.XPath:
                    webElement = Driver.FindElement(By.XPath(attributeValue));
                    break;
            }
            while (!webElement.Displayed)
            {
                i++;
            }
        }
        return webElement;
    }

然后我们可以通过以下方式制作元素:         公共IWebElement webSiteNews => FindWebELement(HtmlAttribute.Id,“ search_query_left”);