简体   繁体   中英

Common Step Definitions in Specflow with Page Object Model

I have a step definition in my login page bindings

[When(@"I click the '(.*)' button")]
public void IClickTheButton(string buttonName)
{
    LoginPage loginPage = new LoginPage();
    loginPage.ClickTheButton(buttonName);
}

My Page objects are set up with the ClickTheButton method in the BasePage:

public class LoginPage : BasePage
{
    public LoginPage(IWebDriver _driver)
    {
        driver = _driver;
    }
    // some methods

}
public class HomePage : BasePage
{
    public HomePage(IWebDriver _driver)
    {
        driver = _driver;
    }
    // some methods
}
public class BasePage
{
    //no constructor atm
    public void ClickTheButton(string buttonName)
    {
        driver.GetFirstButtonWithTextContaining(buttonName).Click();
    }
    // more methods
}      

All buttons in the application are formatted the same so the GetFirstButtonWithTextContaining method will click them all using

driver.FindElements(By.TagName("button")).Where(x => x.Text == buttonName).First();

The problem is I will be using 'I click the '(.*)' button' in all my feature files like the HomePage feature, so it doesn't seem right to use the login page step definition which utilises an instance of the login page class for all the buttons on the other pages.

I was thinking of creating a common step defs file for these type of methods but when I add a constructor to the BasePage (same as the other page object classes) and do the following in the common step defs binding:

BasePage basePage = new BasePage();
basePage.ClickTheButton(buttonName);

Is there a better implementation?...it just seems wrong to use BasePage class but i cant see how to share a step definition across multiple features when using page objects. I'm trying to create as many common steps as possible to share across all features.

Your page models aren't really page models. They are just handy wrappers for doing stuff with Selenium, and are not providing a good layer of abstraction.

Either use the extension methods directly in your step definitions:

[When(@"I click the '(.*)' button")]
public void IClickTheButton(string buttonName)
{
    driver.GetFirstButtonWithTextContaining(buttonName).Click();
}

Or rewrite your page models to encapsulate user actions on the page:

public class LoginPage
{
    private readonly IWebDriver driver;
    private IWebElement Password => driver.FindElement(By.Id("Password"));
    private IWebElement Username => driver.FindElement(By.Id("Username"));
    private IWebElement LoginButton => driver.FindElement(By.XPath("//button[contains(., 'Log In')]"));

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

    public HomePage Login(string username, string password = "test")
    {
        Username.SendKeys(username);
        Password.SendKeys(password);
        LoginButton.Click();

        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

        wait.Until(ExpectedConditions.StalenessOf(LoginButton));

        return new HomePage(driver);
    }
}

That would mean changing your steps from the procedural style (I click this; I do that) to a more behavior driven style. For instance, it is common to "log in" using procedural steps:

Given I am on the login page
When I enter "foo" for the "Username"
And I enter "bar" for the "Password"
And I click the "Log In" button

Instead, a behavior driven step would be a quick one-liner that delegates most of its behavior to a page model:

Given I am logged in as "foo"

[Given(@"I am logged in as ""(.+)""")]
public GivenIAmLoggedInAs(string username)
{
    var loginPage = new LoginPage(driver);

    loginPage.LogIn(username);
}

Your cucumber steps should be a thin veneer gluing the description of application behavior in your feature files to the page models that encapsulate that behavior in a page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM