繁体   English   中英

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

[英]How to initialize SelectElements while using PageFactory / FindsBy in Selenium C#?

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

不幸的是,我发现FindsByAttribute不会初始化SelectElement (HTML <select>标签/下拉菜单)。 到目前为止,我已经碰巧或提出了一些想法来解决它,但它们都不是理想的:

  1. PageFactoryFindsByAttributesealed ,因此我不能仅通过继承它来强制它。
  2. 在每个方法中从IWebElement手动实例化SelectElement是相当混乱和重复的。 它也忽略了PageFactory明显的内置等待并抛出NoSuchElementException除非我每次都添加一个等待 - 这需要在整个地方重复定位器,从而击败(部分)POM的目的。
  3. 使用SelectElement属性包装每个IWebElement属性不太麻烦,但仍然具有与上面相同的等待问题。

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

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

我坚持使用包装器包装(我宁愿避免使用),并且:

[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的调用中轻松指定一个( InitElements更多)。 目前,最好的选择是你的选择3,虽然我不会公开IWebElement成员; 我将其PageFactory private ,因为PageFactory可以像公共成员一样轻松地枚举私有成员。 所以你的页面对象看起来像这样:

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

如何在需要时获得实际的IWebElement 由于SelectElement实现了IWrappedElement ,因此如果需要访问IWebElement接口提供的元素的方法和属性,则可以简单地调用WrappedElement属性。

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

// 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对象。 否则,你所实现的只是一个“页面包装器”,这是一种非常有效的方法,而不是人们称之为“页面对象”的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM