Как инициализировать SelectElements при использовании PageFactory / FindsBy в Selenium c#?
Я создаю объектную модель страницы в Selenium WebDriver для C#, используя PageFactory.
к сожалению, я обнаружил, что FindsByAttribute
не инициализации SelectElement
(HTML-код <select>
tag / выпадающее меню). Я наткнулся или придумал несколько идей, чтобы обойти это до сих пор, но ни одна из них не идеальна:
-
PageFactory
иFindsByAttribute
aresealed
, поэтому я не могу заставить его просто унаследовать их. - создание экземпляра вручную
SelectElement
СIWebElement
в каждом методе довольно грязный и дублирующий. Он также игнорирует кажущееся встроенное ожидание вPageFactory
и бросаетNoSuchElementException
S, Если я не добавляю ожидание каждый раз, когда я это делаю, что потребует повторения локатора повсюду, побеждая (часть) цели POM. - упаковка каждого
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 вне каждого объекта страницы. В противном случае все, что вы реализуете, - это "страница обертка", что является совершенно правильным подходом, просто не то, что можно было бы назвать "объектом страницы"."