c# - 在 Selenium C# 中使用 PageFactory/FindsBy 时如何初始化 SelectElements?

标签 c# selenium drop-down-menu selenium-webdriver pageobjects

我正在使用 PageFactory 在用于 C# 的 Selenium WebDriver 中构建页面对象模型。

不幸的是,我发现 FindsByAttribute不会初始化 SelectElement (HTML <select> 标签/下拉菜单)。到目前为止,我偶然发现或想出了一些解决方法,但没有一个是理想的:

  1. PageFactoryFindsByAttributesealed ,所以我不能仅仅通过继承这些来强制它。
  2. 手动实例化 SelectElement来自 IWebElement每种方法都相当困惑和重复。它还忽略了 PageFactory 中明显的内置等待并抛出 NoSuchElementException除非我每次执行此操作时都添加一个等待时间——这将需要在各处重复定位器,从而破坏(部分)POM 的目的。
  3. 包装每个 IWebElement属性SelectElement属性没那么乱了,但是还是有和上面一样的等待问题。

到目前为止最好的选择是#3,为SelectElement写一个包装器这只是为每种方法增加了等待时间。虽然此解决方案有效,但它会大量增加每个页面的代码,而不是这个(假设的)漂亮代码:

[FindsBy(How = How.Id, Using = "MonthDropdown")]
public SelectElement MonthDropdown;

我被 wrapper wrapper 困住了(这是我宁愿避免的),并且:

[FindsBy(How = How.Id, Using = "MonthDropdown")]
private IWebElement _monthDropdown;
public Selector MonthDropdown
{
    get { return new Selector(MonthDropdown, Wait); }
}

Selector正在SelectElement包装器,还必须包含 IWait<IWebDriver>所以它可以等待,并实例化一个新的 Selector每次我访问它。

有更好的方法吗?

编辑: 昏昏欲睡地输入了错误的访问修饰符。固定的。谢谢,@JimEvans。

最佳答案

首先,.NET PageFactory 实现中没有“内置等待”。您可以在对 InitElements 的调用中轻松指定一个(稍后会详细介绍)。目前,对您来说最好的选择是选项 3,尽管我不会公开 IWebElement 成员;我会将其设置为 private,因为 PageFactory 可以像枚举公共(public)成员一样轻松地枚举私有(private)成员。所以你的页面对象看起来像这样:

[FindsBy(How = How.Id, Using = "MonthDropdown")]
private IWebElement dropDown;
public SelectElement MonthDropdownElement
{
    get { return new SelectElement(dropdown); }
}

如何在需要时获取实际的 IWebElement?由于 SelectElement 实现了 IWrappedElement,如果您需要访问 提供的元素的方法和属性,您可以简单地调用 WrappedElement 属性>IWebElement 接口(interface)。

最新版本的 .NET 绑定(bind)已重构 PageFactory 以使其更具可扩展性。要添加您想要的“内置等待”,您可以执行以下操作:

// Assumes you have a page object of type MyPage.
// Note the default timeout for RetryingElementLocator is
// 5 seconds, if unspecified.
// The generic version of this code looks like this:
// MyPage page = PageFactory.InitElements<MyPage>(new RetryingElementLocator(driver), TimeSpan.FromSeconds(10));
MyPage page = new MyPage();
PageFactory.InitElements(page, new RetryingElementLocator(driver, TimeSpan.FromSeconds(10))); 

此外,如果您真的需要自定义事物的工作方式,我们随时欢迎您实现IPageObjectMemberDecorator,它允许您完全自定义属性的枚举方式和值设置为用这些属性修饰的属性或字段。 PageFactory.InitElements 的(非通用)重载之一采用实现 IPageObjectMemberDecorator 的对象实例。

我将撇开严格定义的页面对象模式的正确实现不应该在每个页面对象之外公开任何 WebDriver 对象。否则,您要实现的只是一个“页面包装器”,这是一种完全有效的方法,而不是所谓的“页面对象”。

关于c# - 在 Selenium C# 中使用 PageFactory/FindsBy 时如何初始化 SelectElements?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31613763/

相关文章:

c# - 向 MemoExEdit 控件添加字符计数器

c# - 字符串 "search and replace"使用 .NET 正则表达式

c# - 在 INotifyPropertyChanged 时调用函数 - UWP c#

python - Selenium 脚本在控制台工作,在 CRON 中不工作 - Geckodriver 错误

android - 如何为菜单项Android添加分线器

c# - 如何使用内存流将 WinForms 应用程序中的 MS Chart 插入到 Outlook 电子邮件中?

运行 testng selenium 测试用例时出现 java.lang.ExceptionInInitializerError

python - 属性错误: module 'selenium.webdriver.common.by' has no attribute 'XPATH' using Selenium Python

HTML 下拉选项比按钮宽

javascript - 没有编辑器插件的数据表内联编辑