Take the 2-minute tour ×
Software Quality Assurance & Testing Stack Exchange is a question and answer site for software quality control experts, automation engineers, and software testers. It's 100% free, no registration required.

Here is an example of some C# WebDriver code I'm using to model a registration page:

public class RegistrationPage : BasePage
{
    private IWebDriver driver;
    private String URL = "http://mydomain.com/registration.aspx";
    // private String pageTitle = "Registration";

    public RegistrationPage(IWebDriver driver) : base(driver)
    {
        this.driver = driver;

        /*
        // if we are not on the Registration page
        if (!(driver.Title.ToString().Equals(pageTitle)))
        {
            throw new Exception(); // Need a more relevant exception
        }*/
    }

    override public String URLproperty
    {
        get { return URL; }
        set { URL = value; }
    }

// CODE OMITTED ...
}

Here is a method from my BasePage, which RegistrationPage uses:

    // Open the URL specified in the implementation of the class
    public virtual void Open()
    {
        driver.Navigate().GoToUrl(this.URLproperty);
    }

And finally here is an example of my test code:

[Test]
    public void SubmitRegistrationWithBlankUserDetails()
    {
        RegistrationPage regPage = new RegistrationPage(driver);
        regPage.Open();
        regPage.ClickRegisterButton();
        Assert.IsTrue(regPage.SearchForText("You must enter a first name"));
    }

The issue I'm having is implementing the title "sanity check" in the constructor (currently commented out) for RegistrationPage. I've seen this used on the WebDriver wiki (here, code in Java I think: http://code.google.com/p/selenium/wiki/PageObjects), but I'm unsure how to go about it.

I see two possible scenarios when running my tests:

  1. My test's [SetUp] points the driver to mydomain.com. A link clicked by WebDriver (for example a link to my Registration page, above) passes the driver to the constructor of whatever page I am visiting. Job done, title sanity check can work.
  2. Let's say instead of clicking links to get to a certain page I want to start my test at the Registration page. I don't have a neat way of visiting that page without navgiating from the domain specified in [Setup]. My [SetUp] doesn't help (unless I navigate manually to the page) and creating a new PageObject of the Registration page doesn't take me anywhere unless I call the Open() method.

Should I simply create a new test plan for the second scenario, one where [Setup] points me to mydomain.com/registration.aspx? Am I misunderstanding something fundamental here?

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

I don't think that you should be defining the URL to the page inside the pageObject. The methods in your page object should actions/ journeys that your pageObjects can take.

For example a login pageObject may have 3 methods in it:

Login(String username, String password) {
// fill in login form
// Submit login form
return new landingPage(driver);
}


LoginUnsuccessfully(String username, String password) {
// fill in login form
// submit login form
return new loginPage(driver, lookForLoginFailMessage);
}

ForgotPassword() {
// click forgot password
return new ForgotPasswordPage();
}

At the start of your page your test should use the driver.get(); (or C# eqivalent) method to navigate to the correct URL, then use the methods in your pageObjects to navigate around your application.

TestLogin() {
driver.get(app.com/login);
Login page login = new LoginPage(driver);
LandingPage landingPage = login.login("joebloggs", "password1");

}

The 'basePage' class that you have should contain 'journeys' that are common to many pages like a navigation menu.

A different 'journey' through the app should be written in another test. But will be able to use the same page objects.


Page Object organisation

PageObjects

  • one for each page in the website / application
  • Contain all the logic about interacting the page
    • how to fill in a form etc
  • All the public methods should be a function that the page can perform

Tests

  • Should only call methods on the page object
  • Each test is a journey through a part of the app

This structure allows for logic of the what you are testing to be separate from the WebDriver interactions with the page

share|improve this answer
    
You're using 'driver.get(app.com/login)' in your test code. Doesn't this mean you're combining the logic and WebDriver interactions? –  Lord Kinboat Jul 15 '13 at 9:07
    
That is just the entry point to the app. I am pointing to this url to find the app, and this is where the tests will start from. I am not interacting with the application in anyway, only telling the browser where the app is. –  Jon Duffy Jul 15 '13 at 9:18
    
So in theory I could declare 'driver.get(app.com/where/I/want/to/go)' for any page, providing my next line passes the driver into the constructor of my PageObject? I'm sure I read somewhere that the tests should not expose the driver object ([Set Up] omitted!)... –  Lord Kinboat Jul 15 '13 at 9:27
    
Would this be so that you could access any page directly? You could yes i'm just not sure why you would want to. The only url this directly put in the the login page at first so the browser can get the the app. After that i just use the page objects to get around the app. I wanted to start the tests at a different point, say a sign up page. I would make another test, called signupTest and the first line might be (driver.get(app.com/signup)); –  Jon Duffy Jul 15 '13 at 9:42
1  
I agree with most of this answer, but I often define a url and a method to navigate directly to it within the page object. As Lord Kinboat pointed out, this allows you to avoid direct references to the webdriver in the test code. Jon is right that most of the time you would not be directly navigating to pages anyways, but when you do it is perfectly acceptable (and in my opinion better) to do so with a function in the page object itself. –  Sam Woods Jul 17 '13 at 1:42
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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