Your opinion on why not to use Page Factory

4,718 views
Skip to first unread message

carina0110

unread,
Nov 13, 2012, 11:03:21 AM11/13/12
to seleniu...@googlegroups.com
[Using Webdriver/Eclipse/TestNG/Java]
 
I have noticed some people considered knowledgeable about Webdriver NOT using PageFactory to initialize page objects. Why? I have decided to use the PageFactory but if those with better knowledge than mine don't use it, I have to wonder why.
 
Thanks
 

sirus tula

unread,
Nov 13, 2012, 11:51:12 AM11/13/12
to seleniu...@googlegroups.com
Correct, It depends on how you use the pagefactory. Some people use pagefactory for element locators wherease some people use it for only the pages of the web application.

Based on my experience, it's better to use page object model for separate pages of the application which means, logon page will have class that has all logon functionalities and so on.

Creating pagefactory element locators will slow the excecution as the driver has to now go to the selenium locator and iterate through all the list to find the exact locator.

Just my two cents.

Thanks.

 

--
You received this message because you are subscribed to the Google Groups "Selenium Users" group.
To post to this group, send email to seleniu...@googlegroups.com.
To unsubscribe from this group, send email to selenium-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/8ICkNZS6vEUJ.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
 
- "If you haven't suffered, you haven't lived your life."
 
Thanks,
 
Sirus

carina0110

unread,
Nov 13, 2012, 12:16:16 PM11/13/12
to seleniu...@googlegroups.com
[BTW, I'm using WebDriver/Eclipse/TestNG/Java]
 
Well, let's say I have to page objects 'LoginPage' and 'HomePage'. Both contain the corresponding elements and methods for each. Here's what some do in the test class:
 
    public class Test () {
        ...
        Login login = new Login(driver);
        login.loginAs(name,pwd);
        Home home = new Home(driver);
        ....
    }
 
    I chose to do this, instead:
   
    public class Test () {
        ...
        login = PageFactory.initElements(driver, Login.class);   // only time I use PageFactory directly in test class
        home = login.loginAs(name,pwd);    // the loginAs() method is responsible for transitioning to the new page
        ....
    }
 
    1. So why would some pros choose the first option over the second?
    2. My understanding is that, with the PageFactory, all elements are initialized and are just waiting to be used. So, with the first approach, I would have to instantiate each element that I want to use, wouldn't I?
 
Thanks

Mark Collin

unread,
Nov 13, 2012, 3:44:35 PM11/13/12
to seleniu...@googlegroups.com

I would classify myself as one of the more experienced Selenium users and I use page factory’s all the time.

 

In my mind they are exactly the right way to do things, make your page factory control the pages and your test assert that everything is as expected.

 

Who is telling you not to use them?

To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/HaX0-xHzNR0J.

autowebtester

unread,
Nov 14, 2012, 6:37:53 AM11/14/12
to seleniu...@googlegroups.com
I came across this article whilst researching how to get started with Webdriver/Page Objects etc. :-

http://iainrose.tumblr.com/post/27612544255/closing-the-page-factory

I can see where he's coming from but I so like the idea of the Page Factory that I use a mix of both.

I class myself as a novice :-)

awt

Mark Collin

unread,
Nov 14, 2012, 5:02:19 PM11/14/12
to seleniu...@googlegroups.com

On his three points:

 

1.       Correct, but that’s true for any WebElement (You can’t create a WebElement if the locator cannot be found).  You can however work around this by using the FindBy object to get a list of elements e.g.:

 

@FindBy(how=How.ID, using =”foo”)

List<WebElement> myElement

 

You can then use the size of the list to find out if the element exists (This is the same as performing a driver.findElements(by.id(“foo”));

 

2.       Not sure what he means here to be honest as he is not exactly clear.  That being said I’m not aware of a way of checking if an WebElement is a child of another WebElement off the top of my head so I don’t see how the page factory is different from using normal WebElement’s.

3.       He’s wrong, you can.  We use elements created in a page factory with ExpectedConditions every day.

 

There are also a few cheats you can do with page factories, one of my favourites is to instantiate a PageFactory using an element rather than a driver object e.g.:

 

https://github.com/Ardesco/Powder-Monkey/blob/master/src/main/java/com/lazerycode/selenium/graphs/HighCharts.java

 

This is very handy when working with things like SVG’s.

 

You can have a page object for a global navigation bar that returns a page object for the page you navigate to every time you click on a link e.g.:

 

@FindBy(how = How.ID, using = "home")

public WebElement homeLink;

@FindBy(how = How.ID, using = "contact")

public WebElement contactUsLink;

 

HomePage followHomePageLink() {

    homeLink.click();

    return new HomePage (driver);

}

 

ContactUsPage followContactUsLink() {

    contactUsLink.click();

    return new ContactUsPage (driver);

}

 

Page objects are extremely powerful if used properly and you can have page objects that use page objects.  This means you can break out global functionality used by all pages if you want to.

To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/Q6vnySadP6YJ.

sirena0110

unread,
Nov 14, 2012, 10:07:12 PM11/14/12
to seleniu...@googlegroups.com
Mark, a couple of things:
 
1. point 3 is referring to most of the canned WebDriverWait ExpectedConditions , which takes a By object as argument. @FindBy gives us a WebElement. In the case of the ExpectedConditions method 'elementToBeClickable (By locator)', how would you use it with an element located using @FindBy?
 
2. Why didn't you use the PageFactory in your example?
 

     HomePage followHomePageLink() {

         homeLink.click();

         return new HomePage (driver);

     }

     I mean, shouldn't you have written "...return PageFactory.initElements(driver, HomePage.class)", instead?

thanks.

Mark Collin

unread,
Nov 15, 2012, 1:24:49 AM11/15/12
to seleniu...@googlegroups.com

In that case point 3 is not clear, I read it to mean that WebElements constructed using a page factory were not compatible with ExpectedConditions (which they are).

 

I agree that you can’t plug WebElements into ExpectedConditions that require a By locator.  From my point of view I don’t see this as a big issue because I see the ExpectedConditions class as a template to do useful things, but I can see that for somebody new to the concept having to write your own is not ideal.

 

As to your second point I usually initElements in the constructor for my page factory (have a look at the link I supplied).  Using the example I linked below my constructor looks like this:

 

public HighCharts(WebDriver driver, WebElement chart) {

  PageFactory.initElements(new DefaultElementLocatorFactory(chart), this);

  this.driver = driver;

  this.chart = chart;

  wait = new WebDriverWait(driver, waitTimeoutInSeconds, 100);

  performAction = new Actions(driver);

}

 

Since the WebElements created by @FindBy are essentially WebElement proxies that find and re-find the associated element every time you invoke them (unless you set them to be cached), you can init them when you construct the object to cut down on line of code.

 

So to answer your question I did, I just use Page Objects in a slightly different way to you J

To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/KAxXhO-S4moJ.

Mike Riley

unread,
Nov 16, 2012, 2:45:48 PM11/16/12
to seleniu...@googlegroups.com
I am not sure if this will do what you mean for #2, but if you do a search for an element using an element, doesn't that limit it to children of the element you are using for the search?

For example:
WebElement parent = driver.findElement(By.xpath("//table"));
WebElement child = parent.findElement(By.xpath("//th"));

That should only find a th tag that is a child of the table.  Obviously you probably would use something a bit more distinguishing that just the tag name, unless the page only had the one table.

One exception is that XPath could be used to find siblings or even parents of the first element using the "../" notation for the path.  Just don't do that and it won't be a problem.

Unless I misunderstood what is wanted.

Mike

Ross Patterson

unread,
Nov 16, 2012, 3:02:16 PM11/16/12
to seleniu...@googlegroups.com

No, parent.findElement() won’t do what you rightly suggest.  I believe that that’s a bug, but several Selenium developers disagree (see Issue 403 http://code.google.com/p/selenium/issues/detail?id=403).  Thus WebElement.findElement(By.xpath(“//...”)) starts at the document root, even though the programmer clearly said “starting at this element”.  I believe all other WebElement.findElement()s are find-within-element, as is WebElement.findElement(By.xpath(locator)) as long as the locator doesn’t start with “//”.

 

Ross

 

From: seleniu...@googlegroups.com [mailto:seleniu...@googlegroups.com] On Behalf Of Mike Riley
Sent: Friday, November 16, 2012 2:46 PM
To: seleniu...@googlegroups.com
Subject: Re: [selenium-users] Your opinion on why not to use Page Factory

 

I am not sure if this will do what you mean for #2, but if you do a search for an element using an element, doesn't that limit it to children of the element you are using for the search?

Mike Riley

unread,
Nov 16, 2012, 3:23:18 PM11/16/12
to seleniu...@googlegroups.com
As I read that bug it is doing exactly what I said.  It treats that element as the start of the DOM to be searched.  The poster of that issue says that is not what they expected it to do, but that is how it worked.

Just as they wrote here:
Instead it incorrectly finds only those nodes which are descendants of p.

Mike

Ross Patterson

unread,
Nov 16, 2012, 3:50:58 PM11/16/12
to seleniu...@googlegroups.com

Yes, but what you missed was that update #9780 (http://code.google.com/p/selenium/source/detail?r=9780) changed the behavior to treat “//” as meaning “from the top of the document” regardless of the context.  In other words, as the issue’s original author wrote:

 

## What steps will reproduce the problem?

 

1. Find an element on the page

2. Do a something like my_element.find_elements(:xpath, '//p')

 

## What is the expected output? What do you see instead?

 

I expect it to find *all* p elements on the page. If I'd wanted to find

only descendants, I'd have done something like:

 

    my_element.find_elements(:xpath, './/p')

 

Note the dot before //p

 

Instead it incorrectly finds only those nodes which are descendants of p.

 

Which is exactly what Selenium has done since release 2.8.  I still think that’s wrong – all other WebElement.findElement() versions search in context except this one – but apparently I’m in the minority.

 

Ross

 

From: seleniu...@googlegroups.com [mailto:seleniu...@googlegroups.com] On Behalf Of Mike Riley
Sent: Friday, November 16, 2012 3:23 PM
To: seleniu...@googlegroups.com
Subject: Re: [selenium-users] Your opinion on why not to use Page Factory

 

As I read that bug it is doing exactly what I said.  It treats that element as the start of the DOM to be searched.  The poster of that issue says that is not what they expected it to do, but that is how it worked.

Just as they wrote here:

Instead it incorrectly finds only those nodes which are descendants of p.


Mike

On Friday, November 16, 2012 12:02:46 PM UTC-8, Ross wrote:

No, parent.findElement() won’t do what you rightly suggest.  I believe that that’s a bug, but several Selenium developers disagree (see Issue 403 http://code.google.com/p/selenium/issues/detail?id=403).  Thus WebElement.findElement(By.xpath(“//...”)) starts at the document root, even though the programmer clearly said “starting at this element”.  I believe all other WebElement.findElement()s are find-within-element, as is WebElement.findElement(By.xpath(locator)) as long as the locator doesn’t start with “//”.

 

Ross

 

From: seleniu...@googlegroups.com [mailto:seleniu...@googlegroups.com] On Behalf Of Mike Riley
Sent: Friday, November 16, 2012 2:46 PM
To: seleniu...@googlegroups.com
Subject: Re: [selenium-users] Your opinion on why not to use Page Factory

 

I am not sure if this will do what you mean for #2, but if you do a search for an element using an element, doesn't that limit it to children of the element you are using for the search?

For example:
WebElement parent = driver.findElement(By.xpath("//table"));
WebElement child = parent.findElement(By.xpath("//th"));

That should only find a th tag that is a child of the table.  Obviously you probably would use something a bit more distinguishing that just the tag name, unless the page only had the one table.

One exception is that XPath could be used to find siblings or even parents of the first element using the "../" notation for the path.  Just don't do that and it won't be a problem.

Unless I misunderstood what is wanted.

Mike

--
You received this message because you are subscribed to the Google Groups "Selenium Users" group.
To post to this group, send email to seleniu...@googlegroups.com.
To unsubscribe from this group, send email to selenium-user...@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/A3J1yb8k-KAJ.

Mark Collin

unread,
Nov 16, 2012, 5:40:15 PM11/16/12
to seleniu...@googlegroups.com

I think what you really want is:

 

WebElement parent = driver.findElement(By.xpath("./descendant::table"));

WebElement child = parent.findElement(By.xpath("./descendant::th"));

Reply all
Reply to author
Forward
0 new messages