+ All Categories
Home > Documents > Notes on Selenium WebDriver

Notes on Selenium WebDriver

Date post: 01-Jun-2018
Category:
Upload: vvenkat123
View: 309 times
Download: 4 times
Share this document with a friend

of 12

Transcript
  • 8/9/2019 Notes on Selenium WebDriver

    1/12

    Notes on Selenium WebDriver

    IntroductionSelenium WebDriver (also called Selenium 2) is a second generation web application test facility. It is the result of

    efforts of Google !houghtWor"s and other development groups as well as prior technology such as Wati#.

    Development on Selenium 2 started about two years ago with a different model of how to operate in the browser.

    Selenium 2 is a combination of prior Selenium development plus a new tool called WebDriver. !his removes theneed for starting up the Selenium server and allows the instrumented browser to interact with the application.

    !he $%I for writing Selenium WebDriver tests is much more ob&ect'oriented with ob&ects for page elements and

    entire pages. ence there isnt a big list of method calls on the main Selenium ob&ect but a set of ob&ects that arecreated using methods on the Driver ob&ect (the e*uivalent of the main Selenium ob&ect) and then methods on those

    ob&ects to perform actions.

    Selenium 2 came went G$ in early'mid 2+,, and is now at version 2.,-.+ released early ebruary 2+,2. Itincludes a compatibility $%I with the prior Selenium $%I which can help with migration though that is not

    discussed here. It is recommended that new development use Selenium 2 with either of the $%Is but movingtoward Selenium 2.

    Browser specific drivers!he WebDrivers are browser'specific implementations of the Selenium 2 $%I. /nli"e Selenium ,.0 which relied on

    a single 1avaScript implementation for all browsers to interact with their page elements and so was limited by whatcould be achieved through 1avaScript the WebDrivers interact with the browsers in the best way possible for that

    browser.

    What this in turn allows is

    ,. #ative "eyboard and mouse interactions. !his mimics the end user interactions with the browser much

    better than what earlier versions of Selenium provided.

    2. %roblems related to same origin policy in Selenium , are now gone.

    3. 4etter support for handling popups and dialogs. !his includes some big problem items li"e upload anddownloads.

    Mobile web supportSelenium 2 now supports running tests in mobile devices. I%hone and $ndroid are the two platforms supported.

    !he way it wor"s is that you have to install an app (a mini selenium server) on the device. !his listens for

    commands which then drive the web browser within the app.

    !his mechanism however will not allow us to test native apps in these devices.

    Resources#o specific boo"s as yet you must rely on web'delivered documents.

    %rimary documentation is athttp55seleniumh*.org5docs5+36webdriver.html

    Good overview athttp55code.google.com5p5selenium5wi"i5GettingStarted

    $ 7eference card for Selenium 2 is available athttp55refcard8.d8one.com5refcard85getting'started'selenium'2+

    Example of Use!he primary classes are WebDriver and Web9lement.

    %age ,

    http://seleniumhq.org/docs/03_webdriver.htmlhttp://seleniumhq.org/docs/03_webdriver.htmlhttp://code.google.com/p/selenium/wiki/GettingStartedhttp://code.google.com/p/selenium/wiki/GettingStartedhttp://refcardz.dzone.com/refcardz/getting-started-selenium-20http://refcardz.dzone.com/refcardz/getting-started-selenium-20http://seleniumhq.org/docs/03_webdriver.htmlhttp://code.google.com/p/selenium/wiki/GettingStartedhttp://refcardz.dzone.com/refcardz/getting-started-selenium-20
  • 8/9/2019 Notes on Selenium WebDriver

    2/12

    public void theUserShouldBeAbleToTypeInQueryTerms() { WebDriver driver = ne !ire"o#Driver()$ driver%&et('http%&oo&le%com')$ Web*lement +uery!ield = driver%"ind*lement(By%n,me('+'))$ +uery!ield%send-eys('c,ts')$ +uery!ield%submit()$

    ,ssertTh,t(driver%&etTitle(). cont,insStrin&('c,ts'))$/

    In this e0ample we create a WebDriver then get a page then find an element and perform operations on it.

    inally we chec" that the page title has changed to contain the e0pected value.

    90cept for the Web9lement class you could perform similar steps with Selenium , however there is much more

    fle0ibility because of the various implementations of WebDriver (for different browsers) and the operations on theWeb9lement provide a good abstraction. 4oth of these class structures are discussed in the sections below.

    Driver Implementations

    WebDriver class is available in several implementations. !he most general is 7emoteWebDriver which allows forthe programmatic specification of the test browser and its runtime. See

    http55code.google.com5p5selenium5wi"i57emoteWebDriver . ere is the $%I

    With the :apabilities interface defined as

    !his enables you to set up irefo0 or other runtime environments including a headless front'end. !he various

    subclasses of 7emoteWebDriver such as irefo0Driver are simply preconfigured versions of 7emoteWebDriver.

    %age 2

    http://code.google.com/p/selenium/wiki/RemoteWebDriverhttp://code.google.com/p/selenium/wiki/RemoteWebDriverhttp://code.google.com/p/selenium/wiki/RemoteWebDriver
  • 8/9/2019 Notes on Selenium WebDriver

    3/12

    !he headless front'end typically uses tml/nitDriver (see http55en.wi"ipedia.org5wi"i5tml/nit ). %lease note

    some of the restrictions on use of 1avaScript in this (it is simply running 7hino as a 1avaScript engine which is not

    entirely the same as current production browsers. See http55code.google.com5p5selenium5wi"i5tml/nitDriver).

    Version Compatibility$pparently there is an update re*uired to the WebDriver library for most updates to browsers such as irefo0. See

    http55stac"overflow.com5*uestions5;;33

  • 8/9/2019 Notes on Selenium WebDriver

    4/12

    %lus you can search for an element within a given elements scope find9lement4y(4y by) and find9lements4y(4y

    by).

    !here are special operations to handle select elements on your web page

    %age =

  • 8/9/2019 Notes on Selenium WebDriver

    5/12

    @ou can create an instance of a Select from a Web9lement that is "nown to represent a select element

    !here is a subclass of Web9lement called 7enderedWeb9lement which also offers position information (si8e clic"

    at location etc.).

    Handling WaitsSee http55seleniumh*.org5docs5+=6webdriver6advanced.html !his describes two types of waits

    $n e0plicit waits is code you define to wait for a certain condition to occur before proceeding further in the code.

    !he worst case of this is !hread.sleep() which sets the condition to an e0act time period to wait. !here are some

    convenience methods provided that help you write code that will wait only as long as re*uired. WebDriverWait in

    combination with 90pected:ondition is one way this can be accomplished.

    WebDriver driver = ne !ire"o#Driver()$driver%&et('httpsomedom,inurl0th,t0del,ys0lo,din&')$

    Web*lement myDyn,mic*lement = (ne WebDriverW,it(driver. 12)) %until(ne *#pected3ondition4Web*lement5(){

    67verridepublic Web*lement ,pply(WebDriver d) {

    return d%"ind*lement(By%id('myDyn,mic*lement'))$//)$

    #ote that 90pected:ondition depends upon the Google Guava library.

    $n implicit wait is to tell WebDriver to poll the DA? for a certain amount of time when trying to find an element or

    elements if they are not immediately available. !he default setting is +. Ance set the implicit wait is set for the lifeof the WebDriver ob&ect instance.

    WebDriver driver = ne !ire"o#Driver()$

    driver%m,n,&e()%timeouts()%implicitlyW,it(12. TimeUnit%S*378DS)$driver%&et('httpsomedom,inurl0th,t0del,ys0lo,din&')$Web*lement myDyn,mic*lement = driver%"ind*lement(By%id('myDyn,mic*lement'))$

    !hese waits are needed for clic"s on the page elements as the WebDriver itself doesnt wait (since the clic" may be

    an a&a0 update)

    Page b!ect Model$ Web9lement is an element in the DA? of a page and ways to find these elements include by name by id and by

    css. !his $%I is ideal for writing %age ob&ects as you can loo" up the Web9lements as the page is opened. orinstance

    public cl,ss 9oo&leSe,rch:,&e {

    protected WebDriver driver$priv,te Web*lement +$priv,te Web*lement btn9$

    public 9oo&leSe,rch:,&e(WebDriver driver) {this%driver = driver$this%+ = driver%"ind*lement(By%n,me('+'))$this%btn9 = driver%"ind*lement(By%n,me('btn9'))$

    /

    %age B

    http://seleniumhq.org/docs/04_webdriver_advanced.htmlhttp://seleniumhq.org/docs/04_webdriver_advanced.htmlhttp://seleniumhq.org/docs/04_webdriver_advanced.html
  • 8/9/2019 Notes on Selenium WebDriver

    6/12

    public void open(Strin& url) {driver%&et(url)$

    /

    public void close() {driver%+uit()$

    /

    public Strin& &etTitle() {return driver%&etTitle()$

    /

    public void se,rch!or(Strin& se,rchTerm) {+%send-eys(se,rchTerm)$btn9%clic;()$

    /

    public void typeSe,rchTerm(Strin& se,rchTerm) {+%send-eys(se,rchTerm)$

    /

    public void clic;7nSe,rch() {

    btn9%clic;()$//

    @ou could also change the constructor to throw an e0ception if a re*uired element is not present. !his is similar to

    the verify%age() behavior in other page models.

    $ further refinement is that you can specify the loo"up of the Web9ements by annotation rather than performinginit yourself if the page is created by the %ageactorys init9lements method (see below). or e0ample

    public cl,ss 9oo&leSe,rch:,&e {

    protected WebDriver driver$

    6!indBy(id='+')priv,te Web*lement se,rch!ield$

    6!indBy(n,me='btn9')priv,te Web*lement se,rchButton$

    public Annot,ted9oo&leSe,rch:,&e(WebDriver driver) {this%driver = driver$

    /

    public void open(Strin& url) {driver%&et(url)$

    /

    public void close() {

    driver%+uit()$/

    public Strin& &etTitle() {return driver%&etTitle()$

    /

    public void se,rch!or(Strin& se,rchTerm) {se,rch!ield%send-eys(se,rchTerm)$se,rchButton%clic;()$

    /

    %age C

  • 8/9/2019 Notes on Selenium WebDriver

    7/12

    public void typeSe,rchTerm(Strin& se,rchTerm) {se,rch!ield%send-eys(se,rchTerm)$

    /

    public void clic;7nSe,rch() {se,rchButton%clic;()$

    //

    Would be created using

    9oo&leSe,rch:,&e p,&e = :,&e!,ctory%init*lements(driver. 9oo&leSe,rch:,&e%cl,ss)$

    4y default each element on the page is loo"ed up each and every time a method is called upon it. !o change this

    behavior simply annotate the field with the Elin" :ache>oo"upF.

    In the above e0ample the %ageactory will create the class (running the constructor) then fill out each of the

    elements. So the constructor can carry out a set of direct element loo"ups as part of verify() se*uence then have the

    %ageactory carry out additional setup and chec"ing.

    uestion there is a #oSuch9lement90ception. When is this thrownH $nswer when find9lement fails either in adirect call or in a call from the %ageactory.

    "ips and #uggestions!here are no specific %age Ab&ect superclasses provided so create your own.

    !he %ageactory is your friend as it handles the initiali8ation of those ob&ects for which the find9lement processing

    is useful. !his includes all pages with specific named idd or classed elements.

    Using WebDriver t$roug$ t$e WebDriver %rails Plugin!he current version of the plug'in is +.3.3 released #ovember 2+,,. !he plug'in provides a class that is a wrapper

    for the page driver called WebDriver%age. or each page that you want to interact with in a test you create a %age

    class e0tending from WebDriver%age.

    !he command to run functional tests isgrails test-app functional

    !o re*uest the irefo0 browser instead of tml/nit usegrails -Dwebdriver.browser=firefox test-app functional

    !he Grails environment (as of Grails ,.3.;) supports &/nit =.

  • 8/9/2019 Notes on Selenium WebDriver

    8/12

    %%%Page = webdriver.open(&'& XXXPage.class)$

    age !bstraction "b#ect ModelWebDriver%age is a very handy class as is supports a number of page'definition and validation features that you

    would otherwise have to write yourself. It supports an e0pected!itle value and an elements specification.

    Subclasses of WebDriver%age have properties that allow access to form fields and te0t on the page and methods that

    you call to &ump to other pages. !he tests then &ust interact with these page ob&ects ma"ing assertions andnavigating around your application. If you change your !?> around (change the ID of an element or add an e0tra

    div for e0ample) you only have to modify a specific part of the page ob&ect and not every test that interacted with

    that element.

    9ssentially using a subclass of WebDriver%age is li"e always instantiating your page with the %ageactory at the

    1ava level. 7eviewing the source of WebDriver%age showed us how it organi8es the chec"s for title the chec"s for

    elements etc.

    owever you could define a constructor for the page and carry out specific find9lement calls to create

    Web9lements. or verification you can override verify(boolean new%age) and call the superclass method thencode your verification steps.

    Web$lement "b#ect Model%rovides a set of classes for the Web9lements and provides an automatic way to create pages such that the Driver is

    passed in and the %ageactory is called. !his provides an even higher'level $%I (or at least more syntacticallyshorter) to the WebDriver and page ob&ects.

    or instance >in"9lement offers the clic"!o() method which ta"es a class ob&ect. !he clic"!o method will clic" the

    lin" a return an instance of the specified page class (which would be for the destination of the lin").

    or documentation on the various specific subclasses of web element see https55bitbuc"et.org5refactor5grails'

    webdriver5src5-fad=--;c=cc5test5unit5pages5test5!estAne%age.groovy. !he full list of such classes is shown below

    %age

  • 8/9/2019 Notes on Selenium WebDriver

    9/12

    ?ost of these are subclasses of WebDriver%age9lement.

    #av9lements include >in"s and implement the following

    If you have a table with "nown columns you can use a !able9lement to access the data inside. In this e0ample the4oo"7ow represents a single trJ within the table. ere is the test

    @Test

    public void testList() {

    ListBooksPage listBooksPage = webdriver.open('/books/list', ListBooksPage)

    assertEquals(["Id", "Title", "Author", "Type", "Used"],

    listBooksPage.books.columnHeaders)

    assertEquals(1, listBooksPage.books.size())

    assertEquals("Cryptonomicon", listBooksPage.books.rows[0].title)

    }

    ere is the page

    class ListBooksPage extends WebDriverPage {

    static expectedTitle = "Book List"

    TableElement books

    static elements = {

    books(By.xpath("//table"))

    }

    }

    class BookRow extends WebDriverPageElement {

    String id

    String title

    String author

    String type

    String used

    static elements = {

    id(By.xpath("td[1]"))

    title(By.xpath("td[2]"))

    author(By.xpath("td[3]"))

    type(By.xpath("td[4]"))

    used(By.xpath("td[5]"))

    }

    }

    %age -

  • 8/9/2019 Notes on Selenium WebDriver

    10/12

    ere is the source for !able9lement

    package org.codehaus.groovy.grails.plugins.webdriver

    import org.openqa.selenium.By

    import org.openqa.selenium.WebElement

    public class TableElement extends WebDriverPageElement {

    List columnHeaders

    List rows

    static elements = {

    columnHeaders(By.xpath("thead/tr/th"))

    rows(find: By.xpath("tbody/tr"), listElement:

    {config.tableRowElement ?: config.genericTypes?.get(0) ?: WebElement})

    }

    public int size() {

    return getRowCount()

    }

    public int getRowCount() {

    rows.size()

    }

    public T getAt(int row) {

    rows.get(row)

    }

    public WebElement getCell(int row, int col) {

    def cells = webElement.findElements(By.xpath("tbody/tr[${row + 1}]/td[${col + 1}]"))

    if (cells.size() == 1) {

    return cells[0]

    }

    int size = size()

    if (size == 0) {

    throw new IllegalArgumentException("The table has no rows")

    }

    if (row < 0 || row > size - 1) {

    throw new IllegalArgumentException

    ("The table doesn't have row ${row}. Valid rows are 0..${size - 1}")

    }

    List columns = webElement.findElements(By.xpath("tbody/tr[${row + 1}]/td"))

    if (columns.size() == 0) {

    throw new IllegalArgumentException("Row ${row} has no columns")

    }

    if (col < 0 || col > columns.size() - 1) {

    throw new IllegalArgumentException

    ("Row ${row} doesn't have column ${col}. Valid columns are 0..${columns.size() - 1}")

    }

    throw new IllegalArgumentException("Can't find a cell at ${row},${col} in the table")

    }

    public WebElement getLink(int row, int col) { getCell(row, col).findElement(By.tagName("a"))

    }

    public List getCells() {

    getRows().collect { WebElement row ->

    row.findElements(By.xpath("td"))

    }

    }

    }

    %age ,+

  • 8/9/2019 Notes on Selenium WebDriver

    11/12

    $%ample &est 'lass!he test classes should e0tend from Groovy!est:ase.

    classUeret extends*roov+et,ae { @-le publicWebDriverHelper webdriver= newWebDriverHelper()

    HomePage /omePage Uer0itPage er0itPage

    @Before publicvoidopenHomePage() { WebDriver driver = webdriver.driver; if(driver instanceofHtmlUnitDriver) { ((HtmlUnitDriver) driver).et!ava"ript#nabled(false); $

    /omePage = webdriver.open(&'& HomePage.class) er0itPage = /omePage.openUer0it() $

    @et publicvoider1/ow() {

    introw,ont = er0itPage.get-ow,ont();

    for(inti = 2; i 3 4at/.min(row,ont 5); i66) { Uer1/owPage er1/owPage = er0itPage.open(i);

    aert7ot7ll(er1/owPage.ername) aert7ot7ll(er1/owPage.email)

    er0itPage = er1/owPage.goo0it() $ $$

    Creating &bstract'(ase Classes for %rails Pages/nli"e the Grails %lug'in for Selenium the Grails %lug'in for WebDriver has no built'in classes for the standard

    Grails pages (i.e. list show edit create). So we have implemented a version of them. ere are the design notes

    $bstract%age

    Simply e0tends WebDriver%age

    $bstractorm%age (e0tends $bstract%age)

    ' get field names K returns list of strings

    ' get field value (given the field name)' set field value (given the field name)

    o must have some special support for dates and selects

    4ase>ist%age (e0tends $bstract%age)

    ' get number of rows

    ' get number of cols' get a cell value' change sort column

    ' page forward

    ' page bac"ward

    4aseShow%age (e0tends $bstract%age)

    ' get field names returns list of strings

    ' get field value (given the field name)

    %age ,,

  • 8/9/2019 Notes on Selenium WebDriver

    12/12

    o returns the value simply as a string

    4ase9dit%age (e0tends $bstractorm%age)

    ' offers a submit

    4ase:reate%age (e0tends $bstractorm%age)

    ' offers a submit

    %age ,2


Recommended