c# - Specflow 步骤定义 - 涉及页面对象时跨功能共享
问题描述
我有许多需要在网页上声明预填充数据的功能文件 - 每个功能文件都有自己的步骤定义文件
例如在客户特征步骤 def 文件中:
[Then(@"I expect all fields on the screen populated with Customer Details from the Database")]
public void PopulatedWithCustomerDetailsFromTheDatabase ()
{
foreach (var entry in dataDictionary)
{
Assert.That(pages.CustomerPage.GetText(entry.Key), Is.EqualTo(entry.Value));
}
}
在公司步骤定义文件中:
[Then(@"I expect all fields on the screen populated with Company Details from the Database")]
public void PopulatedWithCompanyDetailsFromTheDatabase()
{
foreach (var entry in dataDictionary)
{
Assert.That(pages.CompanyDetailsPage.GetText(entry.Key), Is.EqualTo(entry.Value));
}
}
两者都使用相关的页面对象类从页面中获取文本并断言其正确。建议我不要共享这样的步骤定义,因为它们使用我同意的不同页面对象。问题是我需要在另外 50 多个页面上执行此操作,CustomerPage、CompanyDetailsPage、StockPage、DeliveryPage 等...
关于如何构建它以便我在步骤定义中有更多共性的任何建议?- 必须有更好的方法,我只是在复制代码,但努力从架构的角度可视化解决方案。
许多页面共有的动作应该被封装为自己的页面模型,并且页面模型可以由多个页面模型组成——这如何实现?
为了澄清每个页面都是不同的,所以除了上述步骤定义之外,对于地址页面功能,我还有一个步骤定义:
[Then(@"I expect all fields on the screen populated with AddressDetails from the Database")]
public void PopulatedWithAddressDetailsFromTheDatabase()
{
foreach (var entry in dataDictionary)
{
Assert.That(pages.AddressDetailsPage.GetText(entry.Key), Is.EqualTo(entry.Value));
}
}
其中有地址线1,地址线2等字段......
以及具有步骤 def 的 Stock Page 功能:
[Then(@"I expect all fields on the screen populated with Stock from the Database")]
public void PopulatedWithStockFromTheDatabase()
{
foreach (var entry in dataDictionary)
{
Assert.That(pages.StockPage.GetText(entry.Key), Is.EqualTo(entry.Value));
}
}
其中有股票列表字段等...用于 50 个不同的页面
解决方案
您可以参数化页面的名称并保留页面对象的字典。
Then I should see the following details on the "Stock" page:
| Field | Value |
| ... | ... |
Then I should see the following details on the "Company Details" page:
| Field | Value |
| ... | ... |
您将需要每个页面对象实现相同的接口,因此您可以将它们存储在字典中并GetText
在步骤定义中调用它们的方法:
public interface IReadOnlyPageModel
{
string GetText(string key);
}
然后在你的页面模型中实现这个接口:
public class StockDetailsPage : IReadOnlyPageModel
{
// stuff specific to the stock details page
public string GetText(string key)
{
// based on key, return text
}
}
public class CompanyDetailsPage : IReadOnlyPageModel
{
// stuff specific to the company details page
public string GetText(string key)
{
// based on key, return text
}
}
然后,您将需要在步骤定义类中使用字典,当然还有步骤定义:
[Binding]
public class StepDefinitions
{
private readonly Dictionary<string, IReadOnlyPageModel> detailsPages;
public StepDefinitions(IWebDriver driver)
{
// Or however you get access to the IWebDriver object
detailsPages = = new Dictionary<string, IReadOnlyPageModel>()
{
{ "Stock", new StockDetailsPage(driver) },
{ "Company", new CompanyDetailsPage(driver) }
};
}
[Then(@"Then I should see the following details on the ""(.*)"" page:")]
public void ThenIShouldSeeTheFollowingDetailsOnThePage(string pageName, Table table)
{
var page = detailsPages[pageName];
foreach (var row in table.Rows)
{
Assert.That(page.GetText(row["Field"]), Is.EqualTo(row["Value"]));
}
}
}
如果您注意到您的元素定位器似乎都遵循一种模式,您可以创建一个通用页面模型:
public class GenericPageModel : IReadOnlyPageModel
{
private readonly IWebDriver driver;
public GenericPageModel(IWebDriver driver)
{
this.driver = driver;
}
public string GetText(string key)
{
return driver.FindElement(By.XPath($"//caption(contains(., 'Details')]/..//tr[contains(., '{key}')]/td[2]")).Text;
}
}
detailsPages
如果在字段中找不到条目,则修改步骤定义以使用通用页面模型。
var page = detailsPages.ContainsKey(pageName)
? detailsPages[pageName]
: new GenericPageModel(driver); // Or however you get access to your IWebDriver object
推荐阅读
- r - 是否可以在 Rmarkdown 中制作带有引用的表格?
- python - 在python中将xarray复制到更大的xarray?
- c# - out 参数在 C# 中不起作用。为什么?
- python - 为什么驱动器号的绝对路径等于工作目录?
- javascript - Vue.js 2 + Typescript - 全局变量在构建后变得未定义
- visual-studio-code - vscode cmake 从 Visual Studio 17 迁移到 19
- python - 有没有办法从某个页面下载音频
- c# - 如何注入选定项目属性在另一个视图中发生变化时如何注入视图
- google-bigquery - BigQuery 据称每小时分区的表显示为不同的表
- c# - 如何告诉 Android 在某些设备(例如三星)上的应用程序中打开自定义文件类型