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

Como é trabalhar na ThoughtWorks

Uma pergunta recorrente que me fazem é: - E ai, como é trabalhar na ThoughtWorks? Bom, vou tentar responder isso... Pra começar é muito diferente de tudo que já vi aqui no Brasil. Nenhuma das empresas pelas quais passei, ou empresas que ouvi amigos próximos falando sobre o dia-a-dia se aproximam do que eu vejo aqui na ThoughtWorks. Isso tanto para bom, quanto para "não tão bom". A ThoughtWorks te contrata para a Thoughtworks não para um projeto Isso pra mim é algo muito bom, a maioria das empresas de consultoria no Brasil quando querem te contratar falam algo do tipo: "Temos um projeto em Alphaville com duração de 6 meses e possibilidade de prorrogação..." Nesse cenário se tem projeto essas empresas contratam como loucas, e quando chega final do ano e os clientes tem um freezee elas demitem! Para em fevereiro do outro ano começarem a contratar de novo. Isso nunca fez sentido para mim. Na ThoughtWorks, quando você é contratado você vira um ThoughtWorker....

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...