Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 7

In most of the test automation code,test logic code (all this URL concatenation,

html/xml parsing, XPath expression etc)


gets written together, usually in one class or one method.

This form is easy to pick up and is intuitive initially, but it has its problems
:
@Test
public void testCreateUser() throws Exception {
final String firstName = "firstNameSelenium";
final String lastName = "lastNameSelenium";
final String login = "loginSelenium";
selenium.click( "link=Menu" );
selenium.click( "usersMenuItem" );
waitForPageToLoad();
selenium.click( "registerNewUserLink" );
waitForPageToLoad();
Assert.assertTrue( selenium.isElementPresent( "userEditPage" ) );
// Register a new user
selenium.type( "form:firstName", firstName );
selenium.type( "form:lastName", lastName );
selenium.type( "form:login", login );
selenium.type( "password", "secretPassSelenium" );
selenium.type( "form:personalEmail", "perso@perso.com" );
selenium.select( "form:homeCountry", "value=FR" );
selenium.select( "form:access2Add", "label=Business Unit Manager" );
selenium.click( "form:industries:industryToggleLink" );
selenium.click( "form:saveButton" );
waitForPageToLoad();
Assert.assertTrue( selenium.isElementPresent( "userEditPage" ) );
}

Problems with existing test approaches:


*The test cases are very tightly coupled to the html code of the web applicati
on.
*If this code changes your tests will start to break.
*Maintainability of the test cases if the application changes.
*Test logic is hard to understand and modify.
*When test logic is embedded into a large amount of other unrelated code,it's
difficult to see what is tested.
*To add new test cases, one often has to reread the supporting code and find o
ut where is the best point to add new code.
*Test logic becomes hard to understand too.
*Tests become fragile.
Since test logic and supporting code like html parsing are mixed together,one sm
all change in the 'contract' between
the system under test and the test automation code can break the test automation
.
Solution ?
Following the layered approach.
The value of layers is that each specializes in a particular aspect of a compute
r program.
Each chunk of automation code relies on lower-level chunks.
Makes these designs much easier to interpret.
To implement such a design, there needs to be a separation of concerns..
by breaking away data, processing logic and test fixture(where test scripts ar
e written)
Data : the id s and names of HTML elements form the "Data" part of the layered arc
hitecrure.
Each page on the site needs to be mirrored to create a test data object,
the data objects are simple property bags containing the id and names of the HTM
L elements located on the page.
Having all the names and id s of elements on the page in one place means that, whe
n there is change on the page
updating the variables happens in one place
processing Logic:
The reusable logical processing actions is exposed or expected to be exposed is
presented via a manager of the component
or page. Therefore, in the current design there is a manager that you speak with
to perform an action. The manager uses
the data objects to access the HTML elements on the page to perform the task at
hand requested.
The processing logic is contained within the manager objects, it is here where y
ou define common tasks on a page
or component.
Test fixture:
Test scripts for a particular area of the system are produced using interactions
with the managers of the page and
or the managers of component.Allowing the QA / tester / developer to concentrat
e more on the creation of the test
rather than the maintaining of the test. By designing layers of abstraction test
fixtures can build high level readable tests.
Page Object Pattern
With Page Object Pattern, each page is represented as an object and with this wa
y we can seperate the html codes
from your tests
Page object pattern :
A Technique for structuring test code...
* that promotes resue and reduce duplication
* Makes tests readable and robust (less brittle)
* improves maintainability
Basic idea :
* Consolidates the code for interacting with any UI element
* Allows us to model the UI in the tests
* Exposes methods that reflect the things the user
can see and do things on that page eg:
addItemToCart(),login(),saveDraft() etc.
* Hides the details of telling the browser how to do those things
Advantage :
* Test code is very readable
* No duplication of selenium API calls
* Reusable code
* Improves maintainability

Method Chaining :
* Change the signature of user behavior methods so that
they return the page object itself.
* Allows multiple behavior methods to be called in sequence
* All the Page object methods return a reference to page object
* If the "user action" moves the focus to a different page
the method should return that page object.
* Otherwise return the same page object.

Consider an example..
A user will try to login to our page and then will list all the latest news
from the main page using the Page Objects

public class LoginPage


{
protected final DefaultSelenium selenium;
public LoginPage(DefaultSelenium selenium)
{
this.selenium = selenium;
}
//behavior where the method returns different page object.
public DashBoardPage loginAs(String userName,String password)
{
selenium.open("/YourApplication/login.xhtml");
selenium.click("j_username");
selenium.type("j_username", userName);
selenium.click("j_password");
selenium.type("j_password", password);
selenium.click("logbut");
selenium.waitForPageToLoad("30000");
return new DashBoardPage(selenium);
}
}
this login page just logins to the system and returns the DashboardPage.
let s see what dashboard page looks like:
public class DashBoardPage
{
protected final DefaultSelenium selenium;
public DashBoardPage(DefaultSelenium selenium)
{
this.selenium = selenium;
}
public NewsPage goToNewsPage()
{
selenium.click("link=news");
return new NewsPage(selenium);
}
}
and news page:
public class NewsPage
{
protected final DefaultSelenium selenium;
public NewsPage(DefaultSelenium selenium)
{
this.selenium = selenium;
}
public boolean isNewsDisplayed()
{
return selenium.getBodyText().contains("News for today");
}
}
ok a basic setup is here, let s see the a simple test
public class DisplayNewsTest
{
protected DefaultSelenium selenium;
@Before
public void before()
{
selenium = new DefaultSelenium("localhost",4444,"*iexplore","http://localho
st:8190");
selenium.start();
}
@Test
public void shouldLoginAndDisplayNews()
{
LoginPage loginPage = new LoginPage(selenium);
Dashboard dashboard = loginPage.loginAs("admin", "admin");
NewsPage newsPage = dashboard.goToNewsPage();
assertThat(newsPage.isNewsDisplayed(), equalTo(true));
}
}
================================================================================
======================================
//create Data classes which have the corresponding elements and their
//getter methods
public class GoogleHomePageData
{
// All the names and id s or xpaths of elements on the page
private const string SEARCH_BUTTON = "xpath=//*[@testid='search']";
private const string SEARCH_TEXT = "xpath=//*[@testid='search1']";
//getter methods to return the values
public static String getSearchButton()
{ return SEARCH_BUTTON;}
public static String getSearchText()
{ return SEARCH_TEXT;}

}
//Each Data Page will have the corresponding manager class which drives the
actions that are performed on the page through the data objects that are accessi
ble
through getters.
public class GoogleHomePageDataManager
{
private final Selenium selenium;
public GoogleHomePageDataManager(Selenium sel)
{
this.selenium=sel;
}
public GoogleSearchResultsDataManager searchFor(String str)
{
selenium.type(GoogleHomePage.getSearchText(),str);
selenium.click(GoogleHomePage.getSearchButton());
selenium.waitForPageToLoad("5000");
return new GoogleSearchResultsDataManager(selenium,str);
}
}
public class GoogleSearchResultsDataManager
{
private final Selenium selenium;
public GoogleSearchResultsDataManager(Selenium sel,String str)
{
this.selenium=sel;
if(!(string + " - Google Search").equals(selenium.getTitle()))
{
throw new IllegalStateException("This is not the Google Results Page");
}
}
public String getResult(int i)
{
String nameXPath = "xpath=id('res')/div[1]/div[" + (i + 1) + "]/h2/a";
return selenium.getText(nameXPath);
}
}
//once the Data and Managers for each page is ready,we'll have the main fixture
//class which tests the scenario that needs to be tested by creating and invokin
g
//the methods from the DataManager classes.
public class GoogleTest {
private Selenium selenium;
@Before
public void setUp() throws Exception {
selenium = new DefaultSelenium("localhost", 4444, "*firefox",
"http://www.google.com/webhp?hl=en");
selenium.start();
}
@Test
//This test basically checsk to see that the "hello world" string should be
in the
//first page of the results returned.
public void helloWorldShouldBeInFirstPageOfResults()
{
GoogleHomePageDataManager home = new GoogleHomePageDataManager(selen
ium);
GoogleSearchResultsDataManager searchResults = home.searchFor("hello
world");
String firstEntry = searchResults.getResult(0);
assertEquals("Hello world program - Wikipedia, the free encyclopedia
", firstEntry);
}
@After
public void tearDown() throws Exception {
selenium.stop();
}
}

You might also like