Вы можете исключить инициализацию нового объекта того же типа, используя внедрение зависимостей (см. Также внедрение конструктора ). В рамках SpecFlow это включает в себя создание нового экземпляра UniversalSelectors в хук SpecFlow и его регистрацию в контейнере объекта SpecFlow. Затем любой класс определения шага, которому требуется модель страницы, должен включать объект UniversalSelectors в качестве одного из аргументов конструктора, который он передает конструктору модели страницы вместе с объектом веб-драйвера.
Регистрация веб-драйвера и Объект UniversalSelector с каркасом внедрения зависимостей SpecFlow (контейнер объекта):
[Binding]
public class SpecFlowHooks
{
private readonly IObjectContainer container;
public SpecFlowHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeScenario]
public void BeforeScenario()
{
var driver = new ChromeDriver() | FirefoxDriver() // or whatever web driver you use
// Configure the web driver
var universalSelectors = new UniversalSelectors(driver);
container.RegisterInstanceAs<IWebDriver>(driver);
container.RegisterInstanceAs(universalSelectors);
}
}
Теперь добавьте объект UniversalSelectors в аргументы конструктора для моделей страниц:
public class RolesPageModel
{
private readonly IWebDriver Driver;
private readonly UniversalSelectors universalSelectors;
// other properties
public RolesPageModel(IWebDriver driver, UniversalSelectors universalSelectors)
{
Driver = driver;
this.universalSelectors = universalSelectors;
}
public void NavigateToRoles()
{
universalselectors.ClickAdministration();
Thread.Sleep(1000);
universalselectors.ClickSystemUsers();
Thread.Sleep(1000);
Roles.Click();
Thread.Sleep(2000);
}
public void CreateBlankRole()
{
Driver.SwitchTo().DefaultContent();
Driver.SwitchTo().Frame(universalselectors.iFrame);
universalselectors.ClickNewRecord();
Thread.Sleep(2000);
universalselectors.ClickSaveRecord();
Thread.Sleep(2000);
}
}
И приклейте к хранить вещи вместе в ваших определениях шагов, где вам необходимо объявить аргумент UniversalSelectors для этих конструкторов:
[Binding]
public class RoleSteps
{
private readonly RolesPageModel roles;
public Roleteps(IWebDriver driver, UniversalSelectors universalSelectors)
{
roles = new RolesPageModel(driver, universalselectors);
}
[When(@"I create a blank role")]
public void WhenICreateABlankRole()
{
roles.CreateBlankRole();
}
}
Добавление
The реальная проблема, на мой взгляд, заключается в самом классе UniversalSelectors. «Селекторы» (или «локаторы» на языке Selenium) могут быть так же легко объявлены в модели страницы, которая использует локатор. На самом деле, это предпочтительный подход. Страницы имеют общие элементы, такие как навигационные меню и панели поиска. Эти общие элементы страницы должны быть их собственными моделями страниц. Композиция, а не наследование, более полезна:
public class RolesPageModel
{
private readonly IWebDriver Driver;
private readonly NavigationBarPageModel navBar;
private readonly SiteSearchBarPageModel searchBar;
// other properties
public RolesPageModel(IWebDriver driver)
{
this.driver = driver;
navBar = new NavigationBarPageModel(driver);
searchBar = new SiteSearchBarPageModel(driver);
}
public void NavigateToRoles()
{
navBar.GoToRoles();
}
Это упрощает зависимости для всех моделей страниц и полностью устраняет необходимость использования UniversalSelectors.