Skip to main content

Page Object Pattern + WebDriver + Spring

During the last week I had start creating a test suite for a existing web-application which my team is currently working on. So now is good time to share some experience:


The application
A normal old java web application: Java 1.4, Struts 1.1, EJB 2.1, JDBC to persist the data and the anemic design (VO+BO+DAO) but I will talk about in another post...


Page Object Pattern
To map the web page's components inside the test code I used the page object pattern.
This patterns helped me to eliminate duplicated code to access web-page's components.

Basically it consists of classes that maps web-pages, so that if you want to fill a login form from your test classes instead of doing this:

  @Test  
  public void someTest() throws Exception {  
      WebElement userNameField = driver.findElement(By.name("j_username"));  
      userNameField.sendKeys(username);  
      WebElement passwordField = driver.findElement(By.name("j_password"));  
      passwordField.sendKeys(password);  
      WebElement logonButon = driver.findElement(By.xpath("/html/body/center/table/tbody/tr[2]/td/form/input"));  
      //asserts  
  }

You do this:

  
  @Test  
  public void someTest()throws Exception {  
      loginPage.open();  
      loginPage.logon(properties.getUsername(), properties.getPassword());  
      //asserts  
  }  

And inside your LoginPage you have:

   public void logon(String username, String password){   
     String username = readUsernameFromFixture();  
     String password = readpasswordFromFixture();  
     WebElement userNameField = driver.findElement(By.name("j_username"));   
     userNameField.sendKeys(username);   
     WebElement passwordField = driver.findElement(By.name("j_password"));   
     passwordField.sendKeys(password);   
     WebElement logonButon = driver.findElement(By.xpath("/html/body/center/table/tbody/tr[2]/td/form/input"));   
     logonButon.click();   
   }   

One thing that I would like to mention here: Keep your assertions in the test class. The idea of the PageObject class is to keep the maps to the web-page's components and to have some helper methods like the example above, not to have assertions.

Wire things togheter.

So now you will have your test class depending on many of the PageObjects, and each PageObject classes also depends on WebDriver:

IMHO is really boring to wire the classes manually, so there comes in Spring.
Spring is very helpful for tests, it is worthy to check the spring documentation about tests.
With simple annotations and just one piece of XML you can wire the pieces together. Check how will be the annotated sample test class:

package br.com.bright.halfprehalfpospaidapplication.test.online;  
...  
imports...  
...  
@ContextConfiguration(locations = "/applicationContext.xml")  
@RunWith(SpringJUnit4ClassRunner.class)  
public class ExpireNoUsedCreditsFunctionalTest {  
    @Autowired  
    private LoginPage loginPage;  
    @Autowired  
    private HomePage homePage;  
    @Autowired  
    private ViewMobilePage viewMobilePage;  
    @Autowired  
    private ViewMobileResultPage viewMobileResultPage;  
    @Autowired  
    private AuxiliaryClassToCheckDataBase akaDaoOrRepository;  
    @Autowired  
    private MenuPage menuPage;  
    @Autowired  
    private Properties properties;  
    private Integer statusBeforeTest;  
    private Integer codeUnderTest;  
    @Before  
    public void setUp() {  
        statusBeforeTest = null;  
        codeUnderTest = null;  
    }  
    @After  
    public void tearDown() {  
        if (statusBeforeTest != null) {  
            akaDaoOrRepository.updateStatusByCode(statusBeforeTest,  
                    codeUnderTest);  
        }  
        menuPage.Logoff();  
    }  
    @Test  
    public void noCreditsToRevert() throws Exception {  
...  

Yes my friends, you can inject dependencies inside private attributes! :O
Your PageObject classes have to be Spring Bean as well, so that Spring will be able to inject them in your test class:

package br.com.bright.thesameapplication.test.online.page;  
import org.openqa.selenium.By;  
import org.openqa.selenium.WebDriver;  
import org.openqa.selenium.WebElement;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Component;  
@Component  
public class LoginPage extends PageBase{  
    @Autowired  
     public LoginPage(WebDriver webDriver) {  
         super(webDriver);  
     }  
     public void logon(String username, String password){  
         WebElement userNameField = driver.findElement(By.name("j_username"));  
         userNameField.sendKeys(username);  
         WebElement passwordField = driver.findElement(By.name("j_password"));  
         passwordField.sendKeys(password);  
         WebElement logonButon = driver.findElement(By.xpath("/html/body/center/table/tbody/tr[2]/td/form/input"));  
         logonButon.click();  
     }  
}  
And in order to inject the WebDriver in the constructor as a dependency we need it to be a Spring Bean as well, but you cannot annotated it as we just downloaded the WebDriver's jar. To solve that we will use the xml piece. Check this out:


 
 
 
  
  
  
  
 

 
  
  
  
  
 
 
 
  
  
  
  
 
 
 



Next Steps...
Normally when we are coding a test suite for a application we end up with a DSL for the application. Probably I will end up with a parent class with some useful method to interact with the application.
Also as I write this post I found a useful information about a page factory built-in WebDriver's support library. It seens to be very helpful.
See you later.

Comments

  1. I've written about DRY page objects on my blog: Keep Your Page Objects DRY.

    ReplyDelete
  2. hi Roger,

    did you removed xml from above blog intentionally or it is not visible because of some other reasons?
    It will be helpful if you can add it back.

    ReplyDelete
  3. Bro Roger, do you have the project for download for the above example. I need to understand Spring based Webdriver project as one of my client has an implementation. I had worked extensively on Webdriver + Core Java. I need you help if you can share a sample project that uses spring to run the tests.I'm running out of time :( It would be great,helo from your side. I can easily understand Java project.

    ReplyDelete

Post a Comment

Popular posts from this blog

Thunderbird with Microsoft OWA in Ubuntu 11.10

So, you as I are tired of Evolution's problems in Ubuntu 11.10 ? Move on to Thunderbird... To have it working with Microsoft OWA following the these steps: Install DavMail Download and install  DavMail . It will act as a proxy between Thunderbird and your Microsoft webmail. Configure DavMail Some tips:  Exchange 2003: https://mail.company.com/exchange/ Exchange 2007 Webdav mode: https://mail.company.com/owa/ Exchange 2007 EWS mode: https://mail.company.com/owa/ Exchange 2010 EWS mode: https://mail.company.com/owa/ Exchange 2010 EWS mode with unsupported authentication form e.g. Windows Live login:https://mail.company.com/ews/exchange.asmx In my case as I'm behind a proxy I had to mark the option "Use system proxy settings" in the Proxy tab: Click save then you should see a message in your system tray, saying that DavMail is correctly configured. Configuring Thunderbird In Thunderbird main window click menu Fil

3 Milagres

São necessários 3 milagres para virar santo Para virar santo você precisa primeiro fazer 3 milagres. Se você começar numa equipe/empresa nova, lembre-se a não ser que você já seja um autor respeitado você vai precisar conquistar seu espaço/respeito. Para conquistar seu espaço/respeito você precisa fazer as coisas acontecerem. Se esforce e faça os milagres acontecerem, depois de 3 você vira santo e dai as pessoas passam a pedir sua benção.