Как инициализировать SelectElements при использовании PageFactory / FindsBy в Selenium c#?

Я создаю объектную модель страницы в Selenium WebDriver для C#, используя PageFactory.

к сожалению, я обнаружил, что FindsByAttribute не инициализации SelectElement (HTML-код <select> tag / выпадающее меню). Я наткнулся или придумал несколько идей, чтобы обойти это до сих пор, но ни одна из них не идеальна:

  1. PageFactory и FindsByAttribute are sealed, поэтому я не могу заставить его просто унаследовать их.
  2. создание экземпляра вручную SelectElement С 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 каждый раз, когда я открыть он.

есть ли лучший способ сделать это?

EDIT: сонно вставил неправильные модификаторы доступа. Зафиксированный. Спасибо, @JimEvans.

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 осуществляет IWrappedElement, вы можете просто позвонить WrappedElement свойства, если вам нужен доступ к методам и свойствам элементов, предусмотренных 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 вне каждого объекта страницы. В противном случае все, что вы реализуете, - это "страница обертка", что является совершенно правильным подходом, просто не то, что можно было бы назвать "объектом страницы"."