2

I am building a selenium automation framework wherein I have a BasePage class which contains common methods used by all the web pages such as:

verifyTitle and verifyElement. For both the methods, I have used expectedconditions class i.e

ExpectedConditions.titleIs(eTitle) and wait.until(ExpectedConditions.visibilityOf(element).

Code as below:

public void verifyElement(WebElement element){
        WebDriverWait wait = new WebDriverWait(driver, 10);
        try{
            wait.until(ExpectedConditions.visibilityOf(element));
            Reporter.log("Element is present ", true);
        }
        catch(Exception e){
            Reporter.log("Element is not present ", true);
            Assert.fail();
        }
    }

    public void verifyTitle(String eTitle){
        WebDriverWait wait = new WebDriverWait(driver, 10);
        try{
            wait.until(ExpectedConditions.titleIs(eTitle));

            Reporter.log("Page is displayed with title : "+eTitle, true);
        }
        catch(Exception e){
            Reporter.log("Page is not displayed with title : "+eTitle, true);
            Assert.fail();
        }

I have built a POM class for every webpage which extends basePage class In POM class we use encapsulation.

In my test class, I will have to call the method verifyElement of BasePage class and pass the webelement which is initialized in my POM class. How can I do this? Since the webelements in POM class are private, I cannot call them in test class. But, since I have already inspected the element using @findBy I want to reuse the XPath

2 Answers 2

1

If I were you, I`d refactor the code a bit. You seem to have mixed up things which should be in individual test cases into your webpage classes (e.g. "Verify title"). The following approach seems to work well for me, as it splits tests from logic required to control the website. I usually start with:

  • "Browser" or "Client" class - this one initializes the webdriver with preferred settings. It contains all the common functions of a browser and actions which can be done by you in the browser - e.g. "find element using implicit wait", "switch to the next tab", "wait for element to be visible"...
  • Individual page classes - a class for each page on the website you are testing. These pages are initialized with a Browser object (from previous point), so they can locate all the elements themselves using the "find element" and "wait until visible" Browser functions. I also include some "complex" functions.

    For example, "Registration" webpage/class would contain the following methods:

    • fill_out_username(value)
    • fill_out_password(value)
    • click_sign_up_button()
    • register(username, password) - this one calls all the previous functions, and is used in tests and setup methods when you have to register a new account as part of the test case and don`t want to write 3 functions everytime you need to register a new account.
  • "Project" class aggregating everything we have so far. It initializes all the objects we have defined and serves as an API for tests.
  • Now the actual test cases. Create the Project object in the setup method, and yield it (or just parts of it) to the test cases. Individual test cases can then use Browser class (or even directly webdriver) functions for testing the page, e.g. "assert title is Browser.get_current_title()"

Here is an example of how the structure looks like:

Project             # serves as an API for tests
|- Browser          # the actual browser and all its functions
|  |- webdriver
|  |- settings
|
|- Pages            # initialized with Browser object
   |- Registration
   |- Login
   |- Order
Tests               # create Project object in setup methods of test cases

a test case in Python might look like:

class Registration:
    def test_title(project_object):
        registration = project_object.pages.registration
        browser = project_object.browser
        browser.get_page(registration.url)
        assert "our_title" == browser.get_title()

or you could just yield only the things the test class needs, and it would then look like:

class Registration:
    def test_title(browser, registration):
        browser.get_page(registration.url)
        assert "our_title" == browser.get_title()

and somewhere else:

# Although in Python with pytest, you`d use fixtures for setup of the Project 
# object, so the code below would look different in the actual fixture.
project = Project()
registration = Registration()
registration.test_title(project.browser, project.pages.registration)

Feel free to correct me if there`s a better approach, I am always willing to learn new things.

0

You can have methods on the concrete pages:

class HomePage {

    private WebElement userName;

    public void verifyUserName(){
        this.verifyElement(userName);
    }

}

If you want to generate this kind of method, you can use Lombok's Builder.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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