c# - 如何在共享相同对象实例的单独文件/类中编写类的属性

标签 c# selenium selenium-webdriver specflow

我正在使用 C# 和页面对象模型为 Selenium 测试自动化设置一个框架。

框架是使用specflow建立的,其项目结构如下。

  • 特征文件
  • 步骤定义
  • 核心.cs

核心代码如下:

[Binding]
public class Core
{
    private readonly IObjectContainer objectContainer;
    public IWebDriver _driver;
    public Core(IObjectContainer objContainer) => objectContainer = objContainer;

    [BeforeScenario]
    public void BeforeScenario()
    {
        _driver = new ChromeDriver();
        objectContainer.RegisterInstanceAs<IWebDriver>(_driver);
    }
}

步骤定义如下:

[Binding]
public class StepDefinition
{
    public IWebDriver driver;
    public StepDefinition1(IWebDriver _driver) => driver = _driver;

    public IWebElement username => driver.FindElement(By.Id("username"));//property1
    public IWebElement password => driver.FindElement(By.Id("pass"));//property2
    .
    .
    .
    .

    [When(@"i enter data")]
    public void WhenIEnterData()
    {
        username.Click()              
    }
}

我想将 passwordusername 属性放在单独的文件中。以后会有很多属性和很多步骤定义文件。所以我想把所有的属性都放在一个地方。

我尝试拆分类并将两者标记为部分类并使用相同的名称,但如果有很多步骤定义文件,这将不起作用。

public class OR
{ 
    public IWebDriver driver;
    public OR(IWebDriver _driver) => driver = _driver;
    public IWebElement username => driver.FindElement(By.Id("username"));
    public IWebElement password => driver.FindElement(By.Id("pass"));
}

[Binding]
public class StepDefinition1 :OR
{
    public IWebDriver driver;
    public StepDefinition1(IWebDriver _driver) => driver = _driver;

    [When(@"i enter data")]
    public void WhenIEnterData()
    {
        username.Click();
    }
}

但这给了我:

There is no argument given that corresponds to the required formal parameter _driver of OR.OR(IWebDriver) on constructor of stepdefnition1.

因为会有很多步骤定义文件,所以我想将所有属性保存在一个地方,所有类/步骤定义都可以访问。

最佳答案

虽然 Ikacho 的回答可以解决问题,但您的问题最好用不同的类架构来解决。将步骤定义类和 selenium 相关类分开,并利用页面对象模型。

首先是page对象,专用于登录页面:

public class LoginPage
{ 
    public IWebDriver driver;

    public LoginPage(IWebDriver _driver)
    {
        this.driver = _driver;
    }

    private IWebElement Username => driver.FindElement(By.Id("username"));
    private IWebElement Password => driver.FindElement(By.Id("pass"));
    private IWebElement LoginButton => driver.FindElement(By.XPath("//button[contains(., 'Login']"));

    public void LogIn(string username, string password)
    {
        Username.SendKeys(username);
        Password.SendKeys(password);
        LoginButton.Click();
    }
}

还有一个示例步骤定义文件:

[Binding]
public class StepDefinition1
{
    private IWebDriver driver;
    private LoginPage loginPage;

    public StepDefinition1(IWebDriver _driver)
    {
        driver = _driver;
        loginPage = new LoginPage(driver);
    }

    [When(@"I log in")]
    public void WhenIEnterData()
    {
        loginPage.LogIn("test", "test");
    }
}

现在,使用 Selenium API 与 Web 浏览器交互的代码集中在它们自己的类中,为您提供了一种重用该代码的简单方法。它还允许您创建可以处理与网页交互的复杂细节的类,因此这种复杂性不会分散到您的步骤定义中。

根本不需要继承。组合将更简单,更容易重用代码。

关于c# - 如何在共享相同对象实例的单独文件/类中编写类的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57510293/

相关文章:

c# - Developer 和 MSbuild 命令提示符之间有什么区别

c# - 避免冗余的异步计算

c# - 证书 - 什么是 KSP 和 CSP

java - Selenium:如何判断 RemoteWebDriver.findElements(By) 是否可以抛出 StaleElementReferenceException?

Selenium :如何使壁虎驱动 headless

python - 分发涉及 PhantomJS 的 py 程序

c# - 在 List<Parent> 对象的泛型函数中使用子类型

selenium - 如何更改允许站点保存和读取 cookie 数据(推荐)和/或阻止第三方 cookie

php - 如何使用 PHP 和 Facebook WebDriver 上传文件?

python - Selenium:以字符串形式获取列表元素的内容