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:
- using the Singleton pattern
- 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?