Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Page object model selenium Java project

Create a page object model selenium project

Short story:

Last year I attended for SeleniumCamp conference in Kiev, Ukraine, and in one of the presentations the speaker mentioned something that left me speechless   :

It doesn’t matter how your code is structured if does the job , it doesn’t matter if you copy past the same script from a file to another file and just get the job done.

I’m not going to mention the speaker name , but even him said “You might be surprised that Im saying this in a development conference” , well this close me up.

I believe it matters how you structured your code and I believe it’s a waist of time and resources if you don’t make the most of any patter you might use.

What is page object model?

Page Object model is an object design pattern in Selenium, where web pages are represented as classes, and the various elements on the page are defined as variables on the class.

Why Page object Model (POM)?

When you start your UI automation project you might say that is easy enough to get started with selenium but simply as that just imagine the following code:

package com.example.tests;

import com.thoughtworks.selenium.*;
import java.util.regex.Pattern;

public class temp script extends SeleneseTestCase {
    public void setUp() throws Exception {
        setUp("http://localhost:8080/", "*iexplore");
    }
    public void testTemp script() throws Exception {
        selenium.open("/BrewBizWeb/");
        selenium.click("link=Start The BrewBiz Example");
        selenium.waitForPageToLoad("30000");
        selenium.type("name=id", "bert");
        selenium.type("name=Password", "biz");
        selenium.click("name=dologin");
        selenium.waitForPageToLoad("30000");
    }
}

How can you reuse it for another 1000 further tests if you have not implemented it in a page Object Model ? The answer is simple : you’ll not gonna be able to reuse it in any if your scrips , so that’s why people find out that it’s easy to structure your code.

Page object model selenium implementation

I believe each project should have a minimum of a config code where you can read your setup from one place.
package automation.config;

import java.io.*;
import java.util.Properties;

public class TestConfig {
    private static TestConfig testConfig;
    private static String requiredEnvironmentName;
    private static Properties properties;

    public static String valueFor(final String keyName) throws Throwable {
        return getInstance().getProperty(keyName);
    }

    private static TestConfig getInstance() throws Throwable {
        if (testConfig == null) {
            properties = new Properties();
            requiredEnvironmentName = System.getProperty("env", "local");
            populateCommonProperties();
            populateEnvProperties(requiredEnvironmentName);
            testConfig = new TestConfig();
        }
        return testConfig;
    }

    private static void populateCommonProperties() throws Throwable {
        readInPropertiesFile("common");
    }

    private static void populateEnvProperties(final String requiredEnvironment) throws Throwable {
        readInPropertiesFile(requiredEnvironment);
    }

    private static void readInPropertiesFile(String filePath) throws Throwable {
        String propertiesFilePath = String.format("src/test/resources/config/%s.properties", filePath);
        File propertiesFile = new File(propertiesFilePath);
        if(!propertiesFile.exists()) {
            throw new FileNotFoundException(
                    String.format("No properties file found at: %s", filePath));
        }
        InputStream input = new FileInputStream(propertiesFilePath);
        properties.load(input);
        input.close();
    }

    private String getProperty(final String keyName) {
        String value = properties.getProperty(keyName);
        if(value == null) {
            throw new Error(String.format("Key %s not configured for environment %s", keyName, requiredEnvironmentName));
        }
        return value;
    }
}
TestConfig
Inside automation.ui package we keep browser configuration
package automation.ui;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.support.events.EventFiringWebDriver;

import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import static automation.ui.BrowserFactory.getBrowser;
/**
 * 

* Example of a WebDriver implementation that has delegates all methods to a static instance (REAL_DRIVER) that is only * created once for the duration of the JVM. The REAL_DRIVER is automatically closed when the JVM exits. This makes * scenarios a lot faster since opening and closing a browser for each scenario is pretty slow. * To prevent browser state from leaking between scenarios, cookies are automatically deleted before every scenario. *

*

* A new instance of SharedDriver is created for each Scenario and passed to yor Stepdef classes via Dependency Injection *

*

* As a bonus, screenshots are embedded into the report for each scenario. (This only works * if you're also using the HTML formatter). *

*

* A new instance of the SharedDriver is created for each Scenario and then passed to the Step Definition classes' * constructor. They all receive a reference to the same instance. However, the REAL_DRIVER is the same instance throughout * the life of the JVM. *

*/ public class SharedDriver extends EventFiringWebDriver { private static final WebDriver REAL_DRIVER; private static final Thread CLOSE_THREAD = new Thread() { @Override public void run() { REAL_DRIVER.close(); } }; static { Runtime.getRuntime().addShutdownHook(CLOSE_THREAD); try { REAL_DRIVER = getBrowser(); } catch (Throwable throwable) { throwable.printStackTrace(); throw new Error(throwable); } } public SharedDriver() { super(REAL_DRIVER); REAL_DRIVER.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Override public void close() { if (Thread.currentThread() != CLOSE_THREAD) { throw new UnsupportedOperationException("You shouldn't close this WebDriver. It's shared and will close when the JVM exits."); } super.close(); } @Before public void deleteAllCookies() { manage().deleteAllCookies(); } @After public void embedScreenshot(Scenario scenario) { try { byte[] screenshot = getScreenshotAs(OutputType.BYTES); scenario.embed(screenshot, "image/png"); } catch (WebDriverException somePlatformsDontSupportScreenshots) { System.err.println(somePlatformsDontSupportScreenshots.getMessage()); } } }
Shared Driver

Selenium browser factory class:

class BrowserFactory {

    public static WebDriver getBrowser() throws Throwable {
        String desiredBrowserName = System.getProperty("browser", "chrome");
        WebDriver desiredBrowser = null;

        switch(desiredBrowserName) {
            case "ie":
                desiredBrowser = IEBrowser.buildIEBrowser();
                break;
            case "chrome":
                desiredBrowser = ChromeBrowser.buildChromeBrowser();
                break;
            case "firefox":
                desiredBrowser = FirefoxBrowser.buildFirefoxBrowser();
                break;
            default:
                //work out what to do when a browser isn't needed
                break;
        }
        return desiredBrowser;
    }
}
BrowserFactory
Selenium chromeDriver initialisation example:
class ChromeBrowser extends ChromeDriver {
    public static WebDriver buildChromeBrowser() throws Throwable {
    	System.setProperty("webdriver.chrome.driver", TestConfig.valueFor("WebDriverChromeDriverPath"));
        ChromeBrowser browser = new ChromeBrowser();
        browser.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        return browser;
    }
    
    private ChromeBrowser() {
    	super();
    }
}
Chromedriver
Simple page :
public class HomePage {
	private final String url = "http://www.google.com";
	private final WebDriver driver;

	@FindBy(css = "#")
	private WebElement searchField;


	public HomePage(WebDriver commonDriver) {
		driver = commonDriver;
		PageFactory.initElements(driver, this);
	}

	public void load() {
		driver.get(url);
	}

	public void searchFor(String searchString) {
		searchField.clear();
		searchField.sendKeys(searchString + "\n");
	}
}
Cucumber steps:
Feature: Search the web
  As an ignorant
  In order to learn things
  I want to be able to find stuff on the web

  Scenario Outline: Search flats to rent
    Given Im using Google
Selenium java step definition example
public class HomePageSteps {
	private final HomePage searchPage;

	
	private final Logger logger = LoggerFactory.getLogger(HomePageSteps.class);

	public HomePageSteps(HomePage commonSearchPage) {
		searchPage = commonSearchPage;
		
	}

	
	@Given("^Im using Google$")
	public void im_using_Zoopla() throws Throwable {
		logger.info("Loading page");
		searchPage.load();
		logger.debug("Loaded page");
	}

}
Step definition
In order to share the driver instance between steps definitions we use Pico Container as an injector

import automation.ui.SharedDriver;
import cucumber.runtime.java.picocontainer.PicoFactory;

public class PicoDependencyInjector extends PicoFactory {

    public PicoDependencyInjector() {
        addClass(SharedDriver.class);
    }
}
And finally your run cukes class:
@RunWith(Cucumber.class)
@CucumberOptions(plugin={"pretty"}, features = "classpath:", glue = {"automation.stepdefs"}) //if you're on windows add `monochrome=true` for clean output
public class RunCukes { }

In case you are using maven too my maven file looks something like this :

4.0.0JavaTest
    JavaTest
    jar1.0-SNAPSHOTautomationhttp://maven.apache.orgUTF-8UTF-81.84.121.2.42.152.53.01.2.12.19.12.19.11.7.211.1.71.582.9.02.6.2com.jayway.restassured
            rest-assured
            ${rest.assured.version}com.github.tomakehurst
            wiremock
            ${wiremock.version}com.google.code.gson
            gson
            ${gson.version}info.cukes
            cucumber-java
            ${cucumber.version}info.cukes
            cucumber-junit
            ${cucumber.version}info.cukes
            cucumber-picocontainer
            ${cucumber.version}org.picocontainer
            picocontainer
            ${picocontainer.version}junit
            junit
            ${junit.version}testorg.seleniumhq.selenium
            selenium-java
            ${selenium.webdriver.version}testorg.seleniumhq.selenium
            selenium-support
            ${selenium.webdriver.version}org.seleniumhq.selenium
            selenium-firefox-driver
            ${selenium.webdriver.version}org.seleniumhq.selenium
            selenium-chrome-driver
            ${selenium.webdriver.version}org.seleniumhq.selenium
            selenium-ie-driver
            ${selenium.webdriver.version}org.slf4j
            slf4j-api
            ${slf4j.version}ch.qos.logback
            logback-classic
            ${logback.version}cuke
            
                true
            
            --tags @wiporg.apache.maven.plugins
                        maven-failsafe-plugin
                        ${maven.failsafe.plugin.version}integration-testintegration-testverify${cucumber.opts}**/*Cukes.classparallel-cuke
                2
            com.github.temyers
                        cucumber-jvm-parallel-plugin
                        ${cucumber.jvm.parallel.version}generateRunnersvalidategenerateRunnersautomation${project.build.directory}/generated-test-sources/cucumber
                                    src/test/resources/features/target/cucumber-paralleljunit, jsontruetrue"@complete"truesimpleorg.apache.maven.plugins
                        maven-failsafe-plugin
                        ${maven.failsafe.plugin.version}integration-testintegration-testverify${acceptance.test.parallel.count}true**/*IT.class
                maven-compiler-plugin
                3.31.81.8org.apache.maven.plugins
                maven-dependency-plugin
            org.apache.maven.plugins
                maven-surefire-plugin
                ${maven.surefire.plugin.version}
pom.xml

In case you are using other programming language than Java consider reading the following articles :

Create a page object framework with cucumber watir

Creating an Automation Testing Framework With Selenium and SpecFlow

Happy testing

The post Page Object Model Selenium Java project appeared first on TestingRepository.



This post first appeared on Testing Repository - Creating Testing, please read the originial post: here

Share the post

Page object model selenium Java project

×

Subscribe to Testing Repository - Creating Testing

Get updates delivered right to your inbox!

Thank you for your subscription

×