C# 硒元素

C# 硒元素,c#,selenium,C#,Selenium,因此,我为FindElement和FindElement创建了两个通用函数: public class Find { public static IWebElement Element(IWebDriver driver, Func<IWebDriver, IWebElement> expectedCondtions, By locator, IWebElement finder = null, int timeOutInSeconds = 120)

因此,我为
FindElement
FindElement
创建了两个通用函数:

public class Find
{
    public static IWebElement Element(IWebDriver driver, Func<IWebDriver, IWebElement> expectedCondtions, 
        By locator, IWebElement finder = null, int timeOutInSeconds = 120)
    {
        WebDriverWait webDriverWait = CreateWebDriverWait(driver, timeOutInSeconds);
        webDriverWait.Until(expectedCondtions);

        if (finder != null)
            return finder.FindElement(locator);
        return driver.FindElement(locator);
    }

    public static ReadOnlyCollection<IWebElement> Elements(IWebDriver driver, Func<IWebDriver, ReadOnlyCollection<IWebElement>> expectedCondtions, 
        By locator, IWebElement finder = null, int timeOutInSeconds = 120)
    {
        WebDriverWait webDriverWait = CreateWebDriverWait(driver, timeOutInSeconds);
        webDriverWait.Until(expectedCondtions);

        if (finder == null)
            return driver.FindElements(locator);
        return finder.FindElements(locator);

    }

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

如您所见,我将两次向我的
函数发送
定位器
,因此我的问题是有什么方法可以只发送一次?

如果我理解您的意图,那么我将编写一些普遍适用的函数,以使您的代码更干净。这在概念上是一件好事,但我认为在这种情况下,它并没有达到你所希望的。我看到很多人想做这样的事情。他们希望围绕Selenium提供的简单方法创建一个包装器,但最终他们没有简化代码,而是将其变得更复杂,在调用堆栈中添加了另一层内容,可能会引入bug,并创建了一个专有API,任何使用您的代码库的人都必须学习它,而不仅仅是使用基本的Selenium命令。当每个元素都通过一个函数查找时,该函数引入的任何bug或间歇性问题都会出现在套件中的每个脚本中

一个简单的比较:

使用
Find
方法

IWebElement e = Find.Element(Driver, ExpectedConditions.ElementToBeClickable(By.CssSelector("#checkboxes > input")), By.CssSelector("#checkboxes > input"), null, 10);
硒的唯一途径

IWebElement e = new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("#checkboxes > input")));
使用你的方法最终并不是很干净。我将以Selenium-only的方式更进一步,并做类似的事情来重用等待,从而使代码更加干净

WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
IWebElement e = wait.Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("#checkboxes > input")));
IWebElement e2 = wait.Until(ExpectedConditions.ElementToBeClickable(By.Id("checkboxes")));
由于
Until()
返回元素,因此可以像
这样链接操作

如果您使用页面对象模型(一般来说,您应该这样做),您将存储定位器,然后像下面那样使用它们,这使得代码更加干净

wait.Until(ExpectedConditions.ElementToBeClickable(checkboxLocator)).Click();
话虽如此,我还是要这样重写这些

public class Find
{
    public static IWebElement Element(WebDriverWait wait, Func<IWebDriver, IWebElement> expectedCondition)
    {
        return wait.Until(expectedCondition);
    }
    public static IReadOnlyCollection<IWebElement> Elements(WebDriverWait wait, Func<IWebDriver, IReadOnlyCollection<IWebElement>> expectedCondition)
    {
        return wait.Until(expectedCondition);
    }
}

在这一点上,你必须问自己为什么
Find.CreateWebDriverWait()
newWebDriverWait()更好?通过编写这个单独的方法,您获得了什么?通过使用单独的方法创建一个
WebDriverWait
,即使超时时间为10秒,您也可以每次创建一个新实例,尤其是在
Element()
Elements()
中。因此,我在代码中省略了它。

这是非常全面的解释,非常感谢。
wait.Until(ExpectedConditions.ElementToBeClickable(checkboxLocator)).Click();
public class Find
{
    public static IWebElement Element(WebDriverWait wait, Func<IWebDriver, IWebElement> expectedCondition)
    {
        return wait.Until(expectedCondition);
    }
    public static IReadOnlyCollection<IWebElement> Elements(WebDriverWait wait, Func<IWebDriver, IReadOnlyCollection<IWebElement>> expectedCondition)
    {
        return wait.Until(expectedCondition);
    }
}
private static WebDriverWait CreateWebDriverWait(IWebDriver driver, int timeOutInSeconds)
{
    return new WebDriverWait(driver, TimeSpan.FromSeconds(timeOutInSeconds));
}