Tuesday, 7 October 2014

Using Page Factories with Loadable Component!!!

Continues with my previous Post!!!

LoadableComponent is another way to approach PageObjects. LoadableComponent 
is a base class that all of the pages need to extend. The base class has the following 
methods on the interface
             
                   1) get()
                   2) isLoaded()
                   3) load()


 Instead of the usual public class PageObject, we change it:

     public class PageObject extends LoadableComponent<PageObject>

We will have to add overrides for the load() and isLoaded() method. The load method
will load the page for us and the isLoaded() method can allow us to check if the page 
has been loaded correctly.

@override
Protected void load() {
selenium.get("http://book.theautomatedtester.co.uk");
}

@protected void isLoaded() {
String url = selenium.getCurrentUrl();
If (url != "http://book.theautomatedtester.co.uk"){
throw new Exception("The wrong page has loaded");
}
}

As we can see this is just a simple bit of code, but we can make sure that we start 
on the right page when we need to.

Now that we have learnt about LoadableComponents, we should have a look at 
seeing it in action. We need to make changes to our Java Class.


1. The following is how the code should look so far:

public class Chapter2 {
WebDriver selenium;
@FindBy(how= How.NAME, using="verifybutton")
WebElement verifybutton;
public Chapter2(WebDriver selenium){
this.selenium = selenium;
if (!"Chapter 2".equalsIgnoreCase(this.selenium.getTitle())){
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
}
public boolean isButtonPresent(String button){
return selenium.findElements(By.xpath
("//input[@id='"+button+"']")).size()>0;
}
}


2. If we have a look at our Chapter 2 Java class, we can see that we need to extend
LoadableComponent. Since this takes generics we will have to pass in our
PageObject class. It should look like:

public class Chapter2 extends LoadableComponent<Chapter2> {

3. In our constructor, we will have to initialize our page factory. We can remove the
rest of the code in there since that will be moved to load(). It should look like the
following:

public Chapter2(WebDriver selenium){
this.selenium = selenium;
PageFactory.initElements(selenium, this);
}


4. We now need to add our override methods. These will allow us to check that we are
on the right page when we load this component:

@override
Protected void load() {
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
@protected void isLoaded() {
String url = selenium.getCurrentUrl();
If (url != "http://book.theautomatedtester.co.uk/chapter2"){
throw new Exception("The wrong page has loaded");
}
}

5. Now we need to have a look at updating our test to load everything for us.
 To do this we need to change:

@Test
public void ShouldLoadTheHomePageAndThenCheckButtonOnChapter2() {
selenium.get("http://book.theautomatedtester.co.uk");
HomePage hp = new HomePage(selenium);
Chapter2 ch2 = hp.clickChapter2();
assertTrue(ch2.isButtonPresent("but1"));
}

6. To look like this:

@Test
public void ShouldLoadTheHomePageAndThenCheckButtonOnChapter2(){
Chapter2 cht = new Chapter2(selenium).get();
ch2.isButton("but1");
}


7. Run your test. Everything should look like the following:


public class Chapter2 extends LoadableComponent<Chapter2>{
WebDriver selenium;
@FindBy(how= How.NAME, using="verifybutton")
WebElement verifybutton;
public Chapter2(WebDriver selenium){
this.selenium = selenium;
PageFactory.initElements(selenium, this);
}
@override
Protected void load() {
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
@protected
public void isLoaded() {
String url = selenium.getCurrentUrl();
If (url != "http://book.theautomatedtester.co.uk/chapter2"){
throw new Exception("The wrong page has loaded");
}
}
public boolean isButtonDisplayed(String button){
return selenium.findElement(By.id("button")).isDisplayed();
}
}

What just happened?

We have just converted our page object to use the LoadableComponent class 
that comes with the Selenium Project. We saw how we simplified on constructors 
and then just moved this into somewhere easy to maintain. We have seen that 
we can move a lot of the boiler plate code out of our class and rely on it 
being pulled in via LoadableComponent. This means that we no 
longer need to maintain it or we add those items.

Imagine how you have to work with a flow that takes you through a number of pages.
LoadableComponent allows us to set up a workflow. To get this right we need to pass
one in like the following when doing your test setup:

@Before
public void prepareComponents() {
WebDriver selenium = new FirefoxDriver();
HomePage homePage = new HomePage(selenium);
Chapter2 chapter2 = new SecuredPage(selenium, homePage);

}

Monday, 25 August 2014

Using Page Factories with Page Objects!!

Continues with my previous Post!!!

The code that we have learnt to write earlier can be quite verbose.
To clean up our code, we can start to use Page Factories.
This allows us to annotate variables in our page objects with how to search the page.
This means that we don't have to have full
WebElement element = driver.findElement(…); code all over the file.

We can change it to:
@FindBy(how=How.ID, using="foo")
WebElement foo;

As you can see this can make our code slightly easier to read and therefore more
maintainable. If you regularly use other languages like Ruby or Python,
you will notice that they don't have the PageFactory support project.
This is because those languages don't have Factory constructs in the language.
They are not idiomatic and therefore not in the language. To use the
PageFactory project in WebDriver, we will have to make sure that the
we have added it as a dependency.

Let us now update my previous post code from with an example of the PageFactory.

See my  the previous post   and go to Chapter2.java. It should look like the
following example:

Chapter2.java

import org.openqa.selenium;
import junit.framework.Assert;
public class Chapter2 {
WebDriver selenium;
WebElement verifybutton;

public Chapter2(WebDriver selenium){
this.selenium = selenium;
verifybutton = selenium.findElement(By.id("verifybutton"));
if (!"Chapter 2".equalsIgnoreCase(this.selenium.getTitle())){
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
}
public boolean isButtonPresent(String button){
return selenium.findElements(By.xpath("//input[@id='"+button+"']")).size()>0;
}
}

We can then change the line that looks for verify button so that it is not in 
the constructor.  This then changes to:

public class Chapter2 {
WebDriver selenium;

@FindBy(how= How.NAME, using="verifybutton")
WebElement verifybutton;

public Chapter2(WebDriver selenium){
this.selenium = selenium;
if (!"Chapter 2".equalsIgnoreCase(this.selenium.getTitle())){
selenium.get("http://book.theautomatedtester.co.uk/chapter2");
}
}
public boolean isButtonPresent(String button){
return selenium.findElementByXpath('//button[@id='+button+']');
}
}

If you run your test now, you will see it do the same thing but we have not 
called the findElement() method available to WebDriver.

In the test we need to initialize the factory by calling initElements():

TestChapter2.java

import org.openqa.selenium.*;
import org.junit.*;
public class TestChapter2 {
WebDriver selenium;

@Before
public void setUp(){
selenium = new FirefoxDriver();
}

@After
public void tearDown(){
selenium.quit();
}
public Chapter2 clickChapter2(){
clickChapter("2");
return PageFactory.initElements(selenium, Chapter2.class);
}

@Test
public void ShouldLoadTheHomePageAndThenCheckButtonOnChapter2() {
selenium.get("http://book.theautomatedtester.co.uk");
HomePage hp = new HomePage(selenium);
Chapter2 ch2 = hp.clickChapter2();
assertTrue(ch2.isButtonPresent("but1"));
}

}

We can seen how we can get rid of a line of code from a constructor or a method
by adding a decorator to the variable. When our code is compiled, the variable will get
populated at the right time so that we can make sure that it gets the right bit of the
DOM. It will look like our element hasn't been instantiated. When we initialize the
PageFactory, by calling initElements() it will populate the variables with the right data.

Sudhakar.Mangi

Sunday, 24 August 2014

Design Patterns In Selenium

‹‹ Page Object design
‹‹ Using Page Factory in Page Objects
‹‹ Using Loadable Components

Important preliminary points
In this chapter it will be assumed that all files will have the following import statements:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

Page Objects
In this section ,we are going to have a look at how we can apply some best practices to tests. You will learn how to make maintainable test suites that will allow you to update tests in seconds. We will have a look at creating your own DSL so that people can see intent. We will create tests using the Page Object Pattern.

Create a new Java class :
1. Import the relevant Selenium Packages.
2. Create the setup() and  teardown()  method. I prefer the JUnit 4 style of tests and
will show code samples with the annotations.
3. We need to check that the page is on the correct page. For this we will use the
selenium.getTitle to see the page title and then if incorrect move to the
chapter 2 link. We do this because navigating to page is slower than checking the
page's title or any other calls to the page already loaded.
4. We need to then validate that it is correct and then work accordingly. The following
is a code snippet of how we can do this:

if (!"Page 2".equals(selenium.getTitle())){
selenium.get(
"http://book.theautomatedtester.co.uk/chapter2");
}

5. Create the rest of the test to check that items are on the page.

Time for action – moving Selenium steps into private methods
to make tests maintainable

Imagine that you just need to test one page on your site and you have quite a few tests
for this page. A lot of the tests will be using the same code over and over again. This can
be quite annoying to maintain if something changes on the page meaning we have to go
through all the tests to fix this one issue

tests as follows:

@Test
public void shouldCheckButtonOnChapter2Page(){
selenium.get("http://book.theautomatedtester.co.uk");
selenium.findElement(By.link, "Chapter2").click();
Assert.assertEqual(selenium.findElements(
By.id"but1").getSize(), 1);
}
@Test
public void shouldCheckAnotherButtonOnChapter2Page(){
selenium.get("http://book.theautomatedtester.co.uk");
selenium.findElement(By.link, "Chapter2").click();
Assert.assertEqual(selenium.findElements(
By.id,"verifybutton").getSize(), 1);

}

Time for action – using the Page Object Pattern to design tests

Imagine that you have a site that has a number of different pages that you need to test. This
is quite common for a number of sites. We can create an object that represents the page and
then pass the Selenium object in the programming language. So let us now create our first
Page Object against the home page.
1. Create a new Java class in IDEA called HomePage.
2. Import the relevant packages for the tests to run.

3. We will now need a constructor to handle Selenium. You may want to make it go to
the home page when it is instantiated too. An example of this can be seen as follows:

HomePage.java

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class HomePage{
WebDriver selenium;
public HomePage(WebDriver selenium){
this.selenium = selenium;
}
public Chapter2 clickChapter2(){
clickChapter("2");
return new Chapter2(selenium);
}
private void clickChapter(String number){
selenium.findElement(By.linkText("Chapter"+number)).click();
}
}

Chapter2.java

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class Chapter2 {
WebDriver selenium;
public Chapter2(WebDriver selenium){
this.selenium = selenium;
if (!"Chapter 2".equalsIgnoreCase(
this.selenium.getTitle())){
selenium.get(
"http://book.theautomatedtester.co.uk/chapter2");
}
}
public boolean isButtonPresent(String button){
return selenium.findElements(By.xpath("//input[@id='" +
button + "']")).size()>0;
}
}

BestPractises3.java

import org.junit.After;
import org.junit.Before;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class BestPractises3 {
WebDriver selenium;
@Before
public void setUp(){
selenium = new FirefoxDriver();
}
@After
public void tearDown(){
selenium.quit();
}
@Test
public void
ShouldLoadTheHomePageAndThenCheckButtonOnChapter2(){
selenium.get("http://book.theautomatedtester.co.uk");
HomePage hp = new HomePage(selenium);
Chapter2 ch2 = hp.clickChapter2();
assertTrue(ch2.isButtonPresent("but1"));
}
}

If you create these three files you will see it pass. The test is a lot more succinct and
easier to maintain.