一尘不染

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

selenium

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

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

  1. PageFactory并且FindsByAttributesealed,因此我不能仅通过继承它们来强制使用。
  2. 在每种方法中SelectElement从实例手动实例化a IWebElement都是很麻烦且重复的。除非我每次都添加一个等待,否则它也会忽略明显的内置等待PageFactory并抛出NoSuchElementExceptions,这将需要在各处重复定位器,从而破坏了POM的(部分)用途。
  3. IWebElement属性包装每个属性的SelectElement麻烦程度较小,但仍存在与上述相同的等待问题。

到目前为止,最好的选择是#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。


阅读 375

收藏
2020-06-26

共1个答案

一尘不染

首先,.NET PageFactory实现中没有“内置等待”
。您可以在调用中轻松指定一个InitElements(稍后对此进行详细说明)。目前,最适合您的选择是您的选择3,尽管我不会公开该IWebElement成员。我会做到的private,因为PageFactory可以像枚举公共成员一样轻松地枚举私有成员。因此您的页面对象将如下所示:

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

IWebElement在需要时如何获得实际值?自从SelectElement实现以来IWrappedElementWrappedElement如果您需要访问IWebElement接口提供的元素的方法和属性,则可以简单地调用属性。

.NET绑定的最新版本已将重组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对象。否则,您所实现的只是一个“页面包装器”,这是一种非常有效的方法,而不是所谓的“页面对象”。

2020-06-26