extensible selenium framework

33
Building a Flexible & Et ibl F k Extensible Framework Around Selenium Apple Chow Santiago Etchebehere

Upload: mrtwist

Post on 10-Apr-2015

4.516 views

Category:

Documents


5 download

DESCRIPTION

The Strategies and Concepts of Building a Flexible and Extensible Test Framework Around Selenium

TRANSCRIPT

Page 1: Extensible Selenium Framework

Building a Flexible & E t ibl F kExtensible Framework Around Selenium

Apple Chow

Santiago Etchebehere

Page 2: Extensible Selenium Framework

Outline

• Our Challengesg

• Our Design Decisions

• Framework ArchitectureFramework Architecture

• Framework Features

• Our ExperienceOur Experience

• Q & A

Page 3: Extensible Selenium Framework

Our Challenges

• Frequent Requirement Changesq q g

• Complex Web UI

• Multiple Projects to Testp j

• Limited Resources

• Browsers, PlatformsBrowsers, Platforms

Page 4: Extensible Selenium Framework

Design Decisions

• Simplicity– Isolating application actions – Utilities for filling forms– Utilities for interacting with tables– AJAX handling utilities– Uniform way to access UI elements– Uniform way to access UI elements

• Flexibility– Grouping of test cases p g– Custom place holders (configuration & data)– Ability to support non-standard UI elements

Page 5: Extensible Selenium Framework

Design Decisions

• Maintainability/Configurabilityy g y– Externalized configuration

– Reduce data duplication

• Data driven tests– Execute same test against multiple datasets

R d l t t t d d t– Randomly generate structured data

Page 6: Extensible Selenium Framework

Selected Tools

• Selenium RC (http://www.openqa.org/selenium/)( p p q g )

– Locators

– WaitForCondition xpath://img[@alt=“Google”]

– getEval Name: qDOM: document.f.q

When page first loads Now readyWhen page first loads… Now ready…

Name: btnGselenium.waitForCondition("

selenium.isElementPresent('orderBtn')

&& selenium.isEditable('orderBtn')“,

timeout);

Page 7: Extensible Selenium Framework

Selected Tools

• TestNG (http://testng.org/doc/index.html)

@DataProvider(name ="customerDataProvider")public Object[][] customerProvider() {...

}

( p g g )

– @Test configurations

– Data providers}

@Test(dataProvider = "customerDataProvider")

public void test(String id String name) {

• Firebug

public void test(String id, String name) {...

}

Page 8: Extensible Selenium Framework

Framework Architecture

Application Configuration GUI Map Data Map

UI Objects SeleniumHelper Util DataGenerator

Base TestBase Client

Application-Specific Client

Application-Specific Test ClassUses

Page 9: Extensible Selenium Framework

Application Config

<appconfig><parameters>< t l>htt </ t l><protocol>http</protocol><host>www.google.com</host><port></port>

<pagesXml>googlesearch/uimap.xml</pagesXml>j tX l l h/d t l / j tX l<projectXml>googlesearch/datamap.xml</projectXml>

<browserType>FIREFOX</browserType><browserVersion>2.0</browserVersion><timeout>300000</timeout>/</parameters>

</appconfig>

Page 10: Extensible Selenium Framework

UI Object

• UI Element Abstraction

• read/write interface

public class TextUIObject implements UIObject{

public String read() {

return helper.getText(getLocator())

}}

public void write(String value) {

helper.type(getLocator(), value);

}

}

Page 11: Extensible Selenium Framework

UI Map

<page name="searchForm"> < i l t ><uielements>

<uiobject name="search.query" type="text"><locator>q</locator>

</uiobject><uiobject name="search.button“ type="button">

<locator>btnG</locator></uiobject>

</uielements></page>

Page 12: Extensible Selenium Framework

Common vs. Test-case Data

<category name="search"><data name="defaultSearch"><properties><prop name="search.query">United States</prop><prop name="search.button"/>

</properties></data>

references and o errides</category> references and overrides

<testcase id="googleSearch001"><dataset name="searchSet001"><dataref name="search001Query" ref="search.defaultSearch">

<prop name="search query">Argentina</prop><prop name="search.query">Argentina</prop></dataref>

</dataset></testcase>

Page 13: Extensible Selenium Framework

UI Object and Data Mapping

<page name="searchForm"><data name=“searchData"><properties>

<prop name="search.query">United States</prop>

<prop name="search.button"/>

<page name= searchForm > <uielements><uiobject name="search.query"type="text"><locator>q</locator>

</uiobject> p p /</properties></data>

</uiobject>

<uiobject name="search.button"type="button”><locator>btnG</locator>

</ i bj t></uiobject></uielements>

</page>

…seleniumHelper.fillForm(“searchForm”, “searchData”);…

Page 14: Extensible Selenium Framework

Application Client

• Contains methods to abstract interaction with your application.

• Uses Selenium (SeleniumHelper) to emulate the user action with the browser, using information from configuration files.

• Simplifies test case writing.

Page 15: Extensible Selenium Framework

Application Test

• Implements the test cases by feeding the client methods with test case specific data.

• Uses Client's high level• Uses Client s high level method to implement the tests.

V ifi th t t t h• Verifies the output matches the expected result.

Page 16: Extensible Selenium Framework

Test Case flow

Page 17: Extensible Selenium Framework

Test Case flow

Page 18: Extensible Selenium Framework

Test Case flow

Page 19: Extensible Selenium Framework

Test Case flow

Page 20: Extensible Selenium Framework

GoogleSearch Example

• Clients (GoogleSearchClient)

• Tests: hierarchy (e.g. GoogleSearchTest)

BaseClient BaseTest

G l S hCli t

BaseClient

Uses

BaseTest

G l S hT tGoogleSearchClient Uses GoogleSearchTest

... public void basicSearchTest(DataSet dataset){assertNotEmpty(client.basicSearch(

dataSet.getDataObject("searchData"));...

...

public TableObject basicSearch(data);

public TableObject advancedSearch(data);

...

Page 21: Extensible Selenium Framework

Advanced Features

• AJAX Handling Utilities

• Custom UI Objects & Decorators

• Table Objects j

• Placeholders

• Data Generator

• Database Support

Page 22: Extensible Selenium Framework

AJAX Handling (Loaded Condition)

<page name="iGoogle"><page name="search"><loaded-condition><loaded-condition> selenium.isElementPresent("q") &&selenium.isElementPresent("btnG")

</loaded-condition>…

100100

…seleniumHelper.waitForPageToLoad(“iGoogle.search”);…

Page 23: Extensible Selenium Framework

AJAX Handling (Reload Trigger)

<page name="searchResults"><loaded-condition> ... </loaded-condition><uiobject name="nextLink" type="anchor" reloadTrigger="searchResults">

<locator>//a[text()='Next']</locator>ocato //a[te t() e t ] / ocato...

Page 24: Extensible Selenium Framework

Custom UI Object

<uiobject name="elapsedTime"

type="SuggestTextBox">gg<locator>q</locator>

...

public class SuggestTextBox extends AbstractUIObject {public class SuggestTextBox extends AbstractUIObject {

...

public void write(SeleniumHelper helper, String value) {

for (char c : value.toCharArray()) {for (char c : value.toCharArray()) {

helper.type(this.getLocator(), c);

helper.wait(1000);

}

}

...

Page 25: Extensible Selenium Framework

UI Object Decorators

<uiobject name="creditCardNumber" type="text"><locator>...</locator>

bli l BlurDecorator t d UIObj tD t {

<decorator>BlurDecorator</decorator>

...

public class BlurDecorator extends UIObjectDecorator {

...

public void write(String value) {

decoratedObject.write(value);

selenium.fireEvent(decoratedObject.getLocator(),"blur");

}

Page 26: Extensible Selenium Framework

Table Object

<table name="questionsTable" ><locator>//table[@id='questions']</locator>

<uiobject name="unreadQuestions" type="img"><locator>tr[${rownum}]/td[2]/img</locator>

</uiobject>

<uiobject name=“subject" type="anchor"><l t >t [${ }]/td[3]/ </l t ><locator>tr[${rownum}]/td[3]/a</locator>

...

...

TableObject questions = new TableObject("questionsTable");

Map<String, String> firstRow = questions.getRow(1);String subject = questions.readCell(1,3);questions writeCell(1 "subject");questions.writeCell(1, subject );...

Page 27: Extensible Selenium Framework

Placeholders

<appconfig>...• Configuration ...

<host>${sys.testHost}</host><user>${env.USER_NAME}<user>

...</appconfig>

• UI Object

• Data

...<locator>//div[@id='results']/span[${paginationResultNum}]</locator>

......

<data name=“userProfile"><properties>

< “ “> ${ti t }</ ><prop name=“username“>user_${timestamp}</prop> <prop name="name">${dataGenerator.string(10)}</prop><prop name="email">${dataGenerator.email}</prop><prop name="age">${dataGenerator.regex([1..9][0..9])}</prop>

</properties>/</data>

Page 28: Extensible Selenium Framework

Automation Process

1. Define application specific settings (e.g. application URL, browser)

2. Define UI elements map

3. Implement an application client to abstract application actions

4. Define common and test case specific data

5. Implement TestNG test cases that map to test case repository

Page 29: Extensible Selenium Framework

Our Experience

• UI Changes

Location:L ti

Before After

UI Changes

Location:Location:

<uiobject name="location" type="text"><locator>location</locator>

<uiobject name="location" type="select"><locator>location</locator><locator>location</locator>

...<locator>location</locator>

...

UIObject location = page.getUIObject("location");

helper.write(location, countryName);}

Page 30: Extensible Selenium Framework

Our Experience

• Custom UI ObjectCustom UI Object

public class RandomMultiSelectionUIObject extends SelectableUIObject {public String write(String count) {// Generate a list of random values from the possible options. String[] posibleOptions = helper.getSelectOptions(locator);List<String> values = dataGenerator.takeFromList(

A Li t( ibl O ti ) t)Arrays.asList(posibleOptions),count);

...super.write(selectedOptions.toString());

} ...

Page 31: Extensible Selenium Framework

Our Experience

• i18n Test Data

<testcase id="test_001"><dataset name="usData"><dataref name="criteria" ref="contact.defaultSearch"/>

</d t t>

i18n Test Data

</dataset><dataset name="chineseData"> <dataref name="criteria" ref="contact.defaultSearch"/>

<prop name="keyword">廣告服務</prop></dataref>

</dataset></testcase>

@Test(dataProvider="searchDataProvider")

@Testcase(id="test_001")

void testSearch(DataSet set) {

TableObject resutlsTableObject resutls =

getClient().search(set.getDataObject("criteria"));

Page 32: Extensible Selenium Framework

Our Team

• Special thanks to:Special thanks to:– Albert Chen

– Alejandro Bolognaj g

– Ariel Rodriguez

– Nicolas Frontini

– Raul Bajales

– Andrew Salamatov

Page 33: Extensible Selenium Framework

Q & A