Or Smith
Or Smith

Reputation: 3596

Code generation for WebDriver PageObjects

I am trying to create some sort of code generation for Page Object in WebDriver.

I read about it, and watch the next lecture: http://www.youtube.com/watch?v=mSCFsUOgPpw

I also saw some tools which create a page object for each new page in my application, So I know how to identify and create WebElement which relevant for me (by ID or XPath), and create a new page object.

But I have 2 main problems:

  1. How I can know what to to with these elements? Some of them need to be clicked, some need to send keys, some need to be click and then press ENTER, etc.
  2. Navigation - In my test code, I want to navigate between by pages (This is all about Page pattern). How can I know the connection between my page objects?

Upvotes: 2

Views: 3571

Answers (2)

Dmytro Zharii
Dmytro Zharii

Reputation: 291

I’ve been also inspired by this lecture, and after a time exploring of the topic, I would say: this approach of automatic page object generation is possible for some web applications: for instance, the default important controls on .NET/ASPX pages would have id: ctxWebPageName_Container1_Panel1_btnLogin.
You can easily parse the id and get all required information.

However, in general case, the automated page object generation is impossible or very hard and requires some artificial intelligence.

That is why I’ve built my own tool SWD Page Recorder for semi-automating this boring process of manual creating the page object class.
The tool allows to:

  • Add new elements from the browser page
  • Edit and debug recorded web elements: Test and change locators
  • Generate Page Object class file

In order to show the full picture, I am working on another project, a simple framework with PageObjects:
SWD.Starter which introduce the following rules for PageObjects:

Each page can be self-tested:
There is a generic test for each PageObject inside the framework, which opens the Page and asks the PageObject to self-test its elements.
Those tests are implemented as a tiny smoke test suite. First of all, they test the application, but on the other hand, they also check the page object declaration inside the code is still corresponds to the real page.

Service oriented architecture
The web elements of the Page1 cannot be accessed outside the Page1 class. When the test code or another page wants to perform some actions on the Page1, they should call a method, declared inside Page1. All web elements inside Page1 are declared with private or protected modifiers.

By following those rules, I’ve really simplified my life:

  • The process of recording new pages with SWD Page Recorder and generating the PageObject code become much faster and more fun.
  • The smoke test suite fails fast when the PageObjects are not corresponding to the real pages.
  • In order to fix the page object, I need to re-record some of the elements manually with SWD Page Recorder or make the manual modifications. As I’ve said, it is not permitted to directly use the web elements outside the given PageObject; so that the fixes need to be applied only inside the broken pageObject. The other pages

References

Upvotes: 2

Algiz
Algiz

Reputation: 1288

Create a (reusable) page object per widget (widget= button, combobox, textfield, ...). The constructor of a widget accept a WebElement or a By object. Every page object should use the reusable page object. Here is the example of a simple login page.

public class MyLoginPage {
  private TextField mUsername;
  private TextField mPassword;
  private Button mSignon;

  ...

  // getter
  public TextField getUsername() {
    return mUsername;
  }

}

With the use of some heuristics you should be able to choose the correct widget to be use. This should answer your first question.

For the second question. Either you implement specific method on your page object that return you another page object. Something like that:

public MyHomePage clickSignon() {
  this.mSignon.click();
  return new MyHomePage(...);
}

You can also implement the button as a generic class. The method click on the Button widget:

public <T extends Widget> T click() {
   ... // coe that makes the click
   return new T(...);
}

The member declaration inside the login page:

private Button mSignon<MyHomePage>;

So you can write:

MyHomePage hp = loginPage.getSignon().click();

Either you implement a factory of page object. The factory is able to determine the current state of the screen and return you the page objct that match what you see. You can determine that by trying to find some specific element on the screen (i.e. The button for the login is only present on the login page).

Not at all a definitive answer, but I hope it already give you direction. Don't hesitate to post a question in the comment and I will update this answer.

Upvotes: 5

Related Questions