jasonj2232
jasonj2232

Reputation: 41

How to better handle creation of required PageObjects when implementing LoadableComponents in Selenium?

I am learning Automation testing using Selenium, Cucumber, and Java and I have implemented the Page Object Model design pattern. In addition to that I have implemented the LoadableComponents pattern as well and I find it quite useful.

The issue I have with it though is that when you have a component that is nested several levels (i.e. there are several pages/other components that you have to get through to get to this component), you need to create an object for each of those pages to set up everything in the constructor of my test class.

An example from the selenium docs for the following web application structure:

 + ProjectPage
 +---+ SecuredPage
     +---+ EditIssue

This is the first half of the test class for the above application:

public class FooTest {
  private EditIssue editIssue;

  @Before
  public void prepareComponents() {
    WebDriver driver = new FirefoxDriver();

    ProjectPage project = new ProjectPage(driver, "selenium");
    SecuredPage securedPage = new SecuredPage(driver, project, "example", "top secret");
    editIssue = new EditIssue(driver, securedPage);
  }

When the component is nested several levels, this can mean that several page objects would need to be created and this seems like quite an inelegant solution. Is there a better way of doing this?

I looked into Dependency Injection frameworks. SpringBoot is something I have basic knowledge on and the @Autowired functionality seems good for this purpose, but implementing an expansive framework like SpringBoot for a simple purpose like this seems equivalent to cutting vegetables using a broadsword.

I also looked into Guiceberry and PicoContainer. I did not understand how Guiceberry works and PicoContainer still requires you to create the objects in the constructor? I think I was unable to understand it.

Upvotes: 2

Views: 64

Answers (1)

JeffC
JeffC

Reputation: 25730

I have a framework at work and we're running over 2k tests a day. The way I've got things set up is I use @Before just to set up the browser and that's it. Anything else that is specific to the test is in the test itself. I guess if every single one of your tests creates an Issue and you never plan to add tests other than Issue tests, then your current approach makes more sense.

As far as your page object setup, I would do things a little different. Each page object should contain methods that represent actions that can be taken on that page/LoadableComponent. I can't see your site but from what you've described, I would create a method on ProjectPage called editIssue(). Inside that method, I would create the necessary page objects to get that task done. That will clean up all the subpage object creation in the test itself.

It would look more like

FooTest.java

public class FooTest {
    @Before
    public void prepareComponents() {
        WebDriver driver = new FirefoxDriver();
    }

    public void fooTest() {
        ProjectPage projectPage = new ProjectPage(...);
        EditIssue editIssue = projectPage.editIssue(...);
        editIssue.doSomething();
    }
}

ProjectPage.java

public class ProjectPage {
    public EditIssue editIssue(...) {
        SecuredPage securedPage = new SecuredPage(...);
        return new EditIssue(...);
    }
}

EditIssue.java

public class EditIssue {
    public void doSomething(){
        // do something
    }
}

Upvotes: 0

Related Questions