1

I am writing a Java Selenium Test Automation Framework. I am using Page Object Model. I have a Base Page that contains elements and methods that can be used by all of the other Pages that extend the Base Page.

Up to now I did NOT instantiate the Base Page. I instantiated all of the other pages as shown below:

public xxxxxxxxPage() {
    PageFactory.initElements(driver, this);
}

I didn't instantiate the BasePage as I think all of the BasePage elements get instantiated by the other pages that extend it.

However, today I wanted to use a common method that I had put on the BasePage. The method wanted to use an element that was also on the BasePage. However, it couldn't find the element as the BasePage hadn't been instantiated.

So is it ok for me to add the following code to the BasePage or is it the wrong thing to do?

public BasePage() {
    PageFactory.initElements(driver, this);
}
Guy
  • 46,488
  • 10
  • 44
  • 88
Matt
  • 773
  • 2
  • 15
  • 30

1 Answers1

3

Using PageFactory.initElements(driver, this); in BasePage will initiate the elements in the derived classes as well, you can use it in the base class constructor and delete it from the derived page objects.

Guy
  • 46,488
  • 10
  • 44
  • 88
  • This was me. Sorry for not doing that right away. As it seems to me, what you have written is not true. I'm looking at the `PageFactory.initElements` code and what I can see is that `for(Class proxyIn = page.getClass(); proxyIn != Object.class; proxyIn = proxyIn.getSuperclass())` which I understand as that it goes up to the superclasses. Not to the derived. So that calling `initElement` against `BasePage` would not init elements of child pages. – Alexey R. Nov 12 '19 at 17:19
  • @AlexeyR. You are looking at the wrong place, the method `instantiatePage` is what initiate the webelements, not `proxyFields` (you need to look at the first constructor `public static T initElements(WebDriver driver, Class pageClassToProxy)`). And on top of that, create simple program with class B inherit from class A, and print `this` in A constructor. You will get B. – Guy Nov 12 '19 at 17:51
  • Not sure Im getting you right. The constructor you have mentioned acvepts `Class`. In OP's case is using `this` that is refering to OP's object of custom page class (not `Class`) . I'll check with a representative example in my code. Probably I misunderstand how reflection works. Certainly will revert a downvote if Im wrong. – Alexey R. Nov 12 '19 at 17:57
  • @AlexeyR. *The constructor you have mentioned accepts `Class`* exactly, this is how it is able to return the PO to the caller. The rest have `Object` as parameter which is less specific. `this` will always be the derived class, even in the base class. This is how inheritance work. – Guy Nov 12 '19 at 18:03
  • I'm getting back to apologize :) I tested that with `PageA` that extends `PageB` where `PageB` outputs `this.getClass().getName()` in its constructor. Which eventually prints `PageA`. Can you add couple of words explaining what is the mechanism behind that so that people like me would get more clear understanding of the solution and so that I can revert my downvote? – Alexey R. Nov 12 '19 at 18:42
  • @AlexeyR. This is how inheritance work, the base class is actually not created at all, only the derived class. [This](https://stackoverflow.com/a/17914609/5168011) is a good answer. – Guy Nov 12 '19 at 18:50