Selenium Framework using a lot of statics I am writing a Selenium framework that should be really easy for a tester with relatively little Java knowledge to use and write tests for. In order to keep the framework as user friendly as possible, I've noticed that I am writing a lot of statics so that the tester doesn't have to instantiate the page objects and methods every time. This of course goes against the principles of OOP. Before I get in too deep with this I'd like to see if there are viable alternatives to my approach. I'm including below the login page class that instantiates a webdriver Singleton, has a username/password field, and a login button. There are 2 tests for this page that are run using TestNG. All code to follow:

LoginPage.java

public class LoginPage {

    public static WebDriver driver;
    private static String username_selector = "username";
    private static String password_selector = "password";
    private static String login_button_selector = "#loginbutton &gt; input";
    private static String fail_message_selector = "error";


    public static void goTo(String environment_url){
        driver = Driver.getDriver();
        driver.get(environment_url);
    }

    public static void loginAs(String username, String password){
        WebElement user = driver.findElement(By.name(username_selector));
        user.clear();
        user.sendKeys(username);
        WebElement pass = driver.findElement(By.name(password_selector));
        pass.clear();
        pass.sendKeys(password);
        WebElement loginBtn = driver.findElement(By.cssSelector(login_button_selector));
        loginBtn.click();
    }

    public static boolean loginErrorDisplayed(){
        WebElement failMessageContainer = driver.findElement(By.className(fail_message_selector));
            if(failMessageContainer.isDisplayed()){
                return true;
            }
            else return false;
    }

    public static String getLoginErrorMessage(){
        WebElement failMessageContainer = driver.findElement(By.className(fail_message_selector));
        String failMessage = failMessageContainer.getText();
        return failMessage;
    }

}


Driver.java

public class Driver {
    public static WebDriver driver = null;

    public static WebDriver getDriver(){
        if(driver == null){
            driver = new FirefoxDriver();
        }

        return driver; 
    }

    public static void killDriver(){
        driver.quit();
    }
}


LoginTest.java

public class LoginTest {

@Test(priority = 0)
public void loginfail() {
    LoginPage.goTo("http://127.0.0.1:8080/login");
    LoginPage.loginAs("wrong username", "wrongpassword");
    boolean didLoginFail = LoginPage.loginErrorDisplayed();
    Assert.assertTrue(didLoginFail == true, "Bad login was successful");
    if (didLoginFail){
        LoginPage.getLoginErrorMessage();
    }
}

@Test(priority = 1)
public void loginsuccess() {
    LoginPage.loginAs("correct_username", "correctpass");
    boolean didLoginFail = LoginPage.loginErrorDisplayed();
    Assert.assertTrue(didLoginFail == false, "Valid Login was unsuccessful");
}

}
if(failMessageContainer.isDisplayed()){
            return true;
        }
        else return false;


Why not simply return failMessageContainer.isDisplayed()?



@Test(priority = 0)
public void loginfail() {
    LoginPage.goTo("http://127.0.0.1:8080/login");
    LoginPage.loginAs("wrong username", "wrongpassword");
    boolean didLoginFail = LoginPage.loginErrorDisplayed();
    Assert.assertTrue(didLoginFail == true, "Bad login was successful");
    if (didLoginFail){
        LoginPage.getLoginErrorMessage();
    }
}


What about Assert.assertTrue((((didLoginFail == true) == true) == true, ...). I mean, if writing a==true was better than a, then doing it more often must be even better.

The following if is superfluous, the getLoginErrorMessage doesn't get used.




  I've noticed that I am writing a lot of statics so that the tester doesn't have to instantiate the page objects and methods every time.


I'd start by dropping all the static modifiers and making it fluent. With a proper API the tester will happily do the instantiation as it leads them to what they want to do.

I don't find something like

public void loginfail() {
    LoginPage loginPage = new LoginPage()
        .goTo("http://127.0.0.1:8080/login")
        .loginAs("wrong username", "wrongpassword");
    Assert.assertTrue(loginPage.loginErrorDisplayed());
    Assert.assertTrue(loginPage.getLoginErrorMessage().contains("WTF?"));
}


harder to use than the static version. You could provide even more, but this is most probably not worth the effort (you'd sort of do the tester's job by providing fluent versions of all asserts they may need; this goes too far, but might be useful for the most commonly used assertions):

public void loginfail() {
    LoginPage loginPage = new LoginPage()
        .goTo("http://127.0.0.1:8080/login")
        .loginAs("wrong username", "wrongpassword")
        .assertThatLoginErrorDisplayed()
        .assertThatLoginErrorMessageContains("WTF?");
}