2

I have a series of steps in a Cucumber-automated test for a web-site. In some cases, I need to pass the Selenium webdriver instance, such that the test can use it to wait until certain elements on the page are visible, e.g.:

public void userLogin(String username, String password, WebDriver driver) {
    //wait until the element is visible
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOf(element));
    userName.sendKeys(username);
    continue_login.click();
    //...
}

I have seen two ways of getting it done:

  1. using the Singleton pattern
  2. without a Singleton

I. Singleton variant

public class ScenarioContext {
    // instance of singleton class
    private static ScenarioContext scenarioContext;
    private WebDriver driver;

    private ScenarioContext(){
        driver= new FirefoxDriver();
    }

    public static ScenarioContext getInstanceOfScenarioContextClass(){
        if (scenarioContext == null) {
            scenarioContext = new ScenarioContext();
        }
        return scenarioContext;
    }

    public WebDriver getDriver(){
        return driver;
    }
}

Steps Definitions:

 ScenarioContext scenarioContext = ScenarioContext.getInstanceOfScenarioContextClass();

 @Before
    public void setUp() {
        WebDriver driver = scenarioContext.getDriver();
        loginPage = new LoginPage(driver);
        PageFactory.initElements(driver, loginPage);
    }

    @Given("^user navigates to Login page$")
    public void userNavigatesToPage() {
        loginPage.open();
    }

    @When("^user logs in with '(.*)' username and '(.*)' password$")
    public void userLogsInWithUsername(String name, String password) {
        loginPage.userLogin(name,password,scenarioContext.getDriver());
    }
  ....Then
  etc.

II. Without singleton

@Before
    public void setUp() {
        driver = new FirefoxDriver();
        loginPage = new LoginPage(driver);
        PageFactory.initElements(driver, loginPage);
    }

    @Given("^user navigates to Login page$")
    public void userNavigatesToPage() {
        loginPage.open();
    }

    @When("^user logs in with '(.*)' username and '(.*)' password$")
    public void userLogsInWithUsername(String name, String password) {
        loginPage.userLogin(name,password, driver);
    }

It boils down to these:

  • loginPage.userLogin(name,password, scenarioContext.getDriver()) plus an extra class
  • loginPage.userLogin(name,password, driver)

The first form, which uses the Singleton pattern, requires more writing. The latter seems more concise.

What is the best practice? And what is the added value of the Singleton approach, that some forums advocate?

1

Singleton is a kind of architectural pattern. So I would apply it if the requirement to use the single instance of webdriver is a part of the architecture (for example all your tests are to use the same webdriver instance).

If using the same webdriver instance is a sort of ad-hoc then I would implement some specific way to pass the same driver amoung certain specific tests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.