14

I am a new test engineer and have been reading about Page Object Model and implementing them and keep coming across Page Factory. I understand that Page Factory is a POM that provides additional features such as instantiating all elements when calling Page Factory and more readable code for tests (though I'm not completely sold on the readability). To be clear, I'm sold on POM. The reusability of the code and the relative ease of maintenance are great and I'm building in that direction.

The two questions I have come down to:

  • Why do I want to instantiate all the elements instead of doing it on the fly?
  • What are the advantages of Page Factory that I'm missing?
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
Haendler
  • 313
  • 1
  • 2
  • 10

5 Answers5

12

Here's Simon Stewart, Selenium project lead and creator of the Page Factory, at the 2017 SeleniumConf in Austin. During his keynote address he says not to use Page Factory. This section of the talk starts here:

https://youtu.be/gyfUpOysIF8?t=1517

Actual statement is at 27:25.

JeffC
  • 22,180
  • 5
  • 32
  • 55
  • 1
    This was a great talk and well worth the time to watch. It's part of the reason that I don't plan on using page factory. That and the way the web app works means lots of stale elements that are causing problems. – Haendler Sep 22 '17 at 13:55
  • 1
    This is not an Answer to the Question. It should have been a comment instead. – undetected Selenium Sep 25 '17 at 15:07
  • @DebanjanB He asked why use page factory and the answer, from the Selenium Lead Contributor (and others), is don't and he explains why. How is that not an answer to the question? – JeffC Sep 25 '17 at 15:16
  • @JeffC OP's 2 questions are very clear, 1)Why do I want to instantiate all the elements instead of doing it on the fly? 2)What are the advantages of Page Factory that I'm missing?. Your Answer doesn't address either of them. On the contrary you are pointing out Simon's comment on a specific usecase where he said **don't**. But that doesn't stands true for all. `PageFactory` with `POM` is still a way better approach for Test Automation. – undetected Selenium Sep 26 '17 at 04:21
  • @DebanjanB ...and yet he accepted this as the answer. So apparently he found it useful and an answer to his question. You seem to just want to argue because I downvoted your answer. If you actually watch the entirety of the section of the video where Simon talks about PageFactory, he actually states, "Don't use PageFactory." He states or alludes to the whole thing being bad code 25:47, "that was a terrible mistake" 26:08, it's terrible 27:18, the API is terrible 27:22, and finally "don't use PageFactory" 27:25. There is no specific usecase mentioned. I don't know how he could be any more clear – JeffC Sep 26 '17 at 04:51
  • 2
    @JeffC while he repeatedly said don't use PageFactory, he didn't really explain why. "The API is terrible" or "people don't write their own" don't provide much technical justification as to why. That segment could've been more informative than just ranting about it. – k_rollo Jul 14 '18 at 14:49
  • @silver That would be feedback for Simon... I didn't do the talk or write the content. I just linked it as a reliable source of why one shouldn't use it. You can watch other videos on the Selenium yt channel for him and other contributors talking about PageFactory, implicit waits, etc. and why you shouldn't use them. – JeffC Jul 23 '18 at 13:29
  • Yes, that comment wasn't directed at you. It's feedback for the content you linked. I wouldn't say it's "reliable" if it doesn't explain much - no matter who the speaker is. Reliable content answers why's and how's, just so happened this particular video didn't. Will head over to Selenium YT to find more. – k_rollo Jul 24 '18 at 13:59
  • @JeffC Seems silver is pretty correct. You haven't understood the sarcasm Simon presented. Hold on your horses till 27m:50s. Regarding PageFactory, Simon clearly says "I love this stuff, it's good". – undetected Selenium Jul 27 '18 at 21:51
  • @DebanjanB No. If you think he's being sarcastic, you don't understand sarcasm and are trying too hard to justify using PageFactory or just don't understand English that well. It's not even three minutes long... watch it again. Go watch his other videos, they're full of him and others saying don't use this stuff. – JeffC Jul 28 '18 at 01:03
  • @DebanjanB I'm not assuming PageFactory is not a good option... I'm listening to Simon, the lead committer on the Selenium project, state that it shouldn't be used, heeding his advice, and pointing others to what he said by linking to the yt video. You're the only one misleading everyone by ignoring what he said and telling others to do the same. I never said he was "only" anything... and it's "creator", not "creater". I just said you (and others) should heed his advice given his position and experience. – JeffC Jul 28 '18 at 05:49
  • @JeffC This would be my last effort to suggest you that you need to understand the way how Simon was trying to address the issues users (might) faces with _PageObjects_. There are a lot many videos on _PageObjects_ by Simon. Go through them with patience. Hopefully you will discover the replies to all of your question on _PageObjects_. Feel free to raise your question here, stackoverflow volunteers will be happy to help you out. – undetected Selenium Jul 28 '18 at 19:13
  • @DebanjanB I was there in the audience when Simon did that talk in Austin at SeleniumConf last year. I understand what he was saying... Don't use PageFactory (amongst a lot of other things). You can continue to believe what you want. Take your own advice and watch it again with patience... or you could come onto the Selenium Discord channel and ask him for yourself. – JeffC Jul 28 '18 at 23:11
12

A few answers have said that the PageFactory "loads" all the WebElements when it is instantiated - this is not actually correct.

The elements don't load until you access them. It's done through the base classes and a RealProxy. It does use the standard FindElement(s)By methods under the hood, so there is no real performance benefit to having WebElements vs storing the By's and loading them when you need them.

One reason I choose to not use the PageFactory model, is I may have a search for an element that I don't want to exist, and by using the auto-wired approach, it searches to see if it exists before I can say "doesn't exist" in the test.

Another issue is there are subtle differences between how the PageFactory instantiates the WebElement and how Driver.FindBy instantiates them. One that bugs me is that PageFactory's version doesn't implement IWrapsDriver, meaning you can't get the driver used to find the element from the element. This may not seem like much, but it means when you want to write extensions to WebElement methods that in turn need a driver, you have to work out a (much more complicated) way of getting the driver, especially since I believe the PageObjectModel should not have a direct reference to the driver...

But that said, for a lot of cases, the out of the box PageFactory approach is very good. I think that the key to using- or not using- the PageFactory is just to have a consistent approach to how your test code and page object models work and interract - as that is key to maintainability.

AndrewP
  • 1,598
  • 13
  • 24
  • 1
    As I'm digging deeper into this your answer matches what I've found about instantiation. However for the way the web app that I'm testing works, I have to deal with lots of stale elements that are causing problems. So far I don't think page factory will be a good option for this project. I will be using POM. – Haendler Sep 22 '17 at 13:57
  • So, how does your PageObject class look like for initialization of elements? Especially for those who are sometimes present, but not always depending on the data. – FDM May 03 '18 at 10:54
  • @FDM, this is going back a while for me, and i have moved onto different projects that don't rely on selenium/c# . But, my page models have a series of selectors for elements i need to access, which might look like: `private By SomeLink => By.CssSelector("a");` then a series of methods that might interract with them, e.g. `public AnotherPageModel ClickSomeLink() => NavigateTo(SomeLink)`. NavigateTo just performs a "click and wait" (click and waits for all scripts to execute), then returns a new page model that represents the new state. – AndrewP May 03 '18 at 22:50
4

Why do I want to instantiate all the elements instead of doing it on the fly?

If I remember correctly, PageFactory scans for any WebElement properties/fields and their attributes and wraps them with a proxy. At that point you're not touching Selenium server yet (you can check this in server console output). Once you try to access the property the WebElement gets instantiated. So if you only accessed one PO property/field only for that one WebElement is created.

What are the advantages of Page Factory that I'm missing?

The use of attributes make the code much more readable and also easy to generate. It is common to create a tool that generates PageObjects for you.

PageFactory was created to support PageObject pattern, nothing more. You don't have to necessarily use it in order to go PO way.

Finally, if you're curious about how it works in detail, I'd suggest you check the source code. It's what I did when I was just starting with Selenium.

frennky
  • 12,581
  • 10
  • 47
  • 63
1

Why do I want to instantiate all the elements instead of doing it on the fly?

In general, when we initiate any page class through PageFactory, it enables us to load all the desired (defined) WebElements at the same time with which we intend to interact in the coarse of Test Execution.

What are the advantages of Page Factory that I'm missing?

The advantages of using Page Factory is numerous. Some of them are as follows:

  1. Page Factory makes your framework more structured, robust and maintainable.
  2. Changes in the DOM Tree of any individual/multiple page can be accommodated with quite ease.
  3. Through Page Factory, the different calls between @Test class, BrowserFactory, Page Objects and Assertions becomes more cleaner and efficient.
  4. The additional attributes of Page Factory like FindBy(), FindBys, and CacheLookup speeds up our test execution by a huge extent.
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • There are many aspects of your answer that are wrong. PageFactory doesn't load all the elements at class load. It's on an as needed/requested basis. See the YT link in my answer for more details or do some googling. It doesn't eliminate the need for proper waits. It doesn't make the framework more structured, I think you are confusing it with a properly implemented page object model. – JeffC Sep 22 '17 at 15:02
  • @JeffC Thanks. 1) I did mention `enables us to load all the desired (defined) WebElements`. 2) Can you point me to some documention why you believe `It doesn't make the framework more structured`. 3) IMO, `PageFactory` is implemented through `POM` only, in-case I am wrong, please refer me to some concrete documentation. 4) Eliminated the reference to `waits` as per your suggestion. – undetected Selenium Sep 25 '17 at 03:30
  • 1) You said, `when we initiate any page class through PageFactory, it enables us to load all the desired (defined) WebElements at the same time` which made me think that you believe that all the elements are scraped on instantiation (as many do, including me at some point). See some of the other answers for corrections to that. 2) It doesn't, in and of itself, make POM better. The implementation of POM is either good or bad, PageFactory doesn't really affect it. 3) Agreed.. not sure where this came from? – JeffC Sep 25 '17 at 05:15
  • @JeffC Thanks again. 1) `made me think that you believe that all the elements are scraped on instantiation` Not at all. 2) My understanding is when you say `make POM better`, one of the main factor is `better structured`. If I am wrong, please point me to a documentation. 3) In-case you are `not sure where this came from` a lil google will bring it out. **As the Answer is updated now and in the absence of any concrete documentation against my points, can you retract your Downvote?** – undetected Selenium Sep 25 '17 at 05:29
  • The answer to the first question is still misleading/wrong. 1) is not correct. POM does this, not PageFactory. 2) POM does this, not PageFactory. 3) Disagree. 4) `FindBy` and `FindBys` don't speed up execution. `CacheLookup` only might if you tried to access an element more than once but can also lead to stale element exceptions if you aren't careful. But... this is all ignoring the fact that many Selenium contributors recommend against using PageFactory. See my answer. – JeffC Sep 25 '17 at 13:33
  • @JeffC I am sorry. Mentioning **_does this_** and **_does not_** doesn't add any value as a comment or an Answer. If you feel any Answer is wrong you may require to point to an authenticated documentation. You are pointing towards Simon's comment with respect to a typical usecase scenario. But that's not true in all the cases. I am in sync with Simon on daily basis. – undetected Selenium Sep 25 '17 at 13:46
  • 1
    PageFactory is just a factory class... it just helps with the initialization of page objects. You are attributing more than that in your description of the advantages of it. You should probably spend some time understanding what PageFactory actually is. You haven't provided any official documentation to prove your statements. Here's a link to the official docs that supports my statements in that the page mentions none of the advantages that you claim it provides, https://github.com/SeleniumHQ/selenium/wiki/PageFactory. – JeffC Sep 25 '17 at 15:03
0
  • Why do I want to instantiate all the elements instead of doing it on the fly?

    The PageFactory can be used to initialize elements of a Page class without having to use FindElement or FindElements. When you are using the webelement(s) more then once your code gets better readable.

  • What are the advantages of Page Factory that I'm missing?

    You also can use some attributes with the Page Factory. The most obvious is the FindsBy attribute but you can also use the CacheLookup attribute to cache the element once it is looked up once.

Koen Meijer
  • 811
  • 11
  • 19
  • 1
    Koen, The first part makes sense. You are saying that it simplifies the code by reducing the number of calls to find an element on a page if I need it multiple times. On the second part, I've read about problems with the CacheLookup. Specifically, if the web element doesn't exist or can't be found, it will end up with a placeholder that doesn't work and creates a difficult error to track down. Secondly, how do you avoid the risk of stale elements with CacheLookup? I know if I call it it's there and live, but if I've called an element that exists on multiple pages it can go stale. – Haendler Sep 20 '17 at 19:43
  • Not every website is suitable to use the CacheLookup annotation/attribute. I think when a lot of Ajax calls and/or Javascript is used on a website it's becoming a bigger risk. You'll be seeing more stale elements exceptions. But when a site is pretty static the CacheLookup would be a good idea. – Koen Meijer Sep 20 '17 at 19:59
  • I understand. I expect that I won't use CacheLookup much on Tririga since it's all JavaScript. – Haendler Sep 20 '17 at 20:02