Monday 25 August 2014

Using Page Factories with Page Objects!!

Continues with my previous Post!!!

The code that we have learnt to write earlier can be quite verbose.
To clean up our code, we can start to use Page Factories.
This allows us to annotate variables in our page objects with how to search the page.
This means that we don't have to have full
WebElement element = driver.findElement(…); code all over the file.

We can change it to:
@FindBy(how=How.ID, using="foo")
WebElement foo;

As you can see this can make our code slightly easier to read and therefore more
maintainable. If you regularly use other languages like Ruby or Python,
you will notice that they don't have the PageFactory support project.
This is because those languages don't have Factory constructs in the language.
They are not idiomatic and therefore not in the language. To use the
PageFactory project in WebDriver, we will have to make sure that the
we have added it as a dependency.

Let us now update my previous post code from with an example of the PageFactory.

See my  the previous post   and go to Chapter2.java. It should look like the
following example:

Chapter2.java

import org.openqa.selenium;
import junit.framework.Assert;
public class Chapter2 {
WebDriver selenium;
WebElement verifybutton;

public Chapter2(WebDriver selenium){
this.selenium = selenium;
verifybutton = selenium.findElement(By.id("verifybutton"));
if (!"Chapter 2".equalsIgnoreCase(this.selenium.getTitle())){
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
}
public boolean isButtonPresent(String button){
return selenium.findElements(By.xpath("//input[@id='"+button+"']")).size()>0;
}
}

We can then change the line that looks for verify button so that it is not in 
the constructor.  This then changes to:

public class Chapter2 {
WebDriver selenium;

@FindBy(how= How.NAME, using="verifybutton")
WebElement verifybutton;

public Chapter2(WebDriver selenium){
this.selenium = selenium;
if (!"Chapter 2".equalsIgnoreCase(this.selenium.getTitle())){
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
}
public boolean isButtonPresent(String button){
return selenium.findElementByXpath('//button[@id='+button+']');
}
}

If you run your test now, you will see it do the same thing but we have not 
called the findElement() method available to WebDriver.

In the test we need to initialize the factory by calling initElements():

TestChapter2.java

import org.openqa.selenium.*;
import org.junit.*;
public class TestChapter2 {
WebDriver selenium;

@Before
public void setUp(){
selenium = new FirefoxDriver();
}

@After
public void tearDown(){
selenium.quit();
}
public Chapter2 clickChapter2(){
clickChapter("2");
return PageFactory.initElements(selenium, Chapter2.class);
}

@Test
public void ShouldLoadTheHomePageAndThenCheckButtonOnChapter2() {
selenium.get("http://book.theautomatedtester.co.uk");
HomePage hp = new HomePage(selenium);
Chapter2 ch2 = hp.clickChapter2();
assertTrue(ch2.isButtonPresent("but1"));
}

}

We can seen how we can get rid of a line of code from a constructor or a method
by adding a decorator to the variable. When our code is compiled, the variable will get
populated at the right time so that we can make sure that it gets the right bit of the
DOM. It will look like our element hasn't been instantiated. When we initialize the
PageFactory, by calling initElements() it will populate the variables with the right data.

Sudhakar.Mangi

No comments:

Post a Comment