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));
}