c# - 不必要的类实例化重复
问题描述
目前正在使用 C# 和 SpecFlow 构建自动化框架。目前我的一个抱怨是我实例化一个类以访问方法或 Web 元素的次数。
下面是我在单独的类方法中实例化的类的一部分
public class UniversalSelectors : BasePage
{
public UniversalSelectors(IObjectContainer container): base(container) { }
//iFrame
public IWebElement iFrame => Driver.FindElement(By.Id("content"));
//Nav Bar Elements
public void ClickAdministration()
{
Driver.FindElement(By.XPath("//a[@id='administration-menu-item']"));
}
public void ClickDevicesMenu()
{
Driver.FindElement(By.XPath("//*[@id='manage-devices-menu-item']"));
}
public void ClickRemoteMonitoring()
{
Driver.FindElement(By.Id("manage-monitoring-menu-item"));
}
public void ClickSystemUsers()
{
Driver.FindElement(By.XPath("//*[@id='manage-users-menu-header']"));
}
//Quick Search Elements
public IWebElement Quick_Search => Driver.FindElement(By.XPath("//*[@class='pSearch pButton']"));
public IWebElement Quick_Search_Box => Driver.FindElement(By.XPath("//*[@class='qsbox']"));
public IWebElement Quick_Search_Button => Driver.FindElement(By.XPath("//*[@class='btn btn-sm btn-success flexigrid-search-button']"));
public IWebElement Quick_Clear_Button => Driver.FindElement(By.XPath("//*[@class='btn btn-sm btn-success flexigrid-clear-button']"));
下面你可以看到我是如何在不同类的每个方法中实例化的。但我想知道的是,这是必要的还是有更好的解决方法?
public void NavigateToRoles()
{
var universalselectors = new UniversalSelectors(_container);
universalselectors.ClickAdministration();
Thread.Sleep(1000);
universalselectors.ClickSystemUsers();
Thread.Sleep(1000);
Roles.Click();
Thread.Sleep(2000);
}
public void CreateBlankRole()
{
var universalselectors = new UniversalSelectors(_container);
Driver.SwitchTo().DefaultContent();
Driver.SwitchTo().Frame(universalselectors.iFrame);
universalselectors.ClickNewRecord();
Thread.Sleep(2000);
universalselectors.ClickSaveRecord();
Thread.Sleep(2000);
}
解决方案
您可以使用依赖注入消除初始化相同类型的新对象(另请参阅构造函数注入)。在 SpecFlow 的范围内,这涉及在SpecFlow 挂钩中创建 UniversalSelectors 的新实例并将其注册到 SpecFlow 对象容器中。接下来,任何需要页面模型的步骤定义类都应该包含一个 UniversalSelectors 对象作为其构造函数参数之一,并将其与 Web 驱动程序对象一起传递给页面模型的构造函数。
使用 SpecFlow 依赖注入框架(对象容器)注册 Web Driver 和 UniversalSelector 对象:
[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();
}
}
附录
在我看来,真正的问题是 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 的需求。
推荐阅读
- angular7 - angular 7+ ionic 4 无法绑定到“数据集”,因为它不是“画布”的已知属性
- c# - MVC:AJAX 处的锚标记查询字符串不被控制器拾取
- c - 如何访问指向结构的指针的成员?
- php - 表单动作不起作用使用php插入数据ajax
- mysql - 从 2 个不同的表中选择多列并计算所选列
- vaadin-grid - Vaadin 流:网格条件背景颜色
- julia - 在DifferentialEquations.jl中的n个回调之后是否有一种惯用的方法来终止集成
- javascript - Tempus-dominus 和 sweetalert2
- apache-flink - Flink,使用 Hadoop 兼容性时的奇怪行为
- ios - Xcode 一直显示:-1: SWIFT_VERSION '5.0' is unsupported, 支持的版本是:3.0, 4.0, 4.2。任何解决方案?