Better Selenium Tests with Geb - Selenium Conf 2014

Preview:

DESCRIPTION

Slide of my Selenium Conference 2014 2014 - Sept 6, 2014.

Citation preview

Better Selenium Tests with GebNaresha K

Enteleki Solutions naresha.k@gmail.com

@naresha_k

WebDriver

ChromeDriver FirefoxDriver InternetExplorerDriver

http://martinfowler.com/bliki/PageObject.html

WebDriver

ChromeDriver FirefoxDriver InternetExplorerDriver

Selenium server

WebDriverJS

https://www.flickr.com/photos/pagedooley/3028798210

Level of Abstraction

WebDriver

ChromeDriver FirefoxDriver InternetExplorerDriver

Selenium server

WebDriverJS

Any problem in computer science can be solved with another

layer of indirection

David Wheeler

https://www.flickr.com/photos/pc_plod/14187378533

Web Driver

Geb

Browser

import geb.Browser!import org.openqa.selenium.firefox.FirefoxDriver!!Browser browser = new Browser(driver: new FirefoxDriver())!

Browserimport geb.Browser!import org.openqa.selenium.firefox.FirefoxDriver!!Browser browser = new Browser(driver: new FirefoxDriver())!

// driver.get("http://seleniumconf.org/")!browser.go 'http://seleniumconf.org/'!

External Config// GebConfig.groovy!import org.openqa.selenium.firefox.FirefoxDriver!!driver = { !! def driverInstance = new FirefoxDriver() !! driverInstance.manage().window().maximize() !! driverInstance !} !

Browser browser = new Browser()!!// driver.get("http://seleniumconf.org/")!browser.go 'http://seleniumconf.org/'!browser.quit()!

Accessing Elements// driver.findElement(By.name("j_username")) !def username = browser.$(name: 'j_username')!

// username.sendKeys("user1")!username << 'user1'!

println username.value()!

Geb Browser

Hello GebBrowser browser = new Browser()!browser.go “http://localhost:8000/app/login.html"!browser.$(name: 'j_username') << 'user1'!browser.$(name: 'j_password') << 'secret'!browser.$('#submit').click()!browser.quit()!

Hello Geb - Improved

Browser.drive{!! go “http://localhost:8000/app/login.html"!! $(name: 'j_username') << 'user1'!! $(name: 'j_password') << 'secret'!! $('#submit').click()!}.quit()!

Configurable URL

Browser.drive{!! go “login.html”!! $(name: 'j_username') << 'user1'!! $(name: 'j_password') << 'secret'!! $('#submit').click()!}.quit()!

// GebConfig.groovy!baseUrl = "http://localhost:8000/app/" !

Assertion

assert $('h1').text() == 'Dashboard'!

Navigator API

Navigator Syntax

$(<css selector>, <index or range>, <attribute / text matchers>)

<h2>Introduction</h2>!<h2>Navigator</h2>!<h2>Page Objects</h2>!<h2>Summary</h2>!

$('h2').text() == 'Introduction'!

$('h2', 1).text() == 'Navigator'!

$('h2').size() == 4!

<h2>Introduction</h2>!<h2>Navigator</h2>!<h2>Page Objects</h2>!<h2>Summary</h2>!

$('h2', 0..2)*.text() == !! ! ['Introduction', 'Navigator', 'Page Objects']!

<h2 duration="5">Introduction</h2>!<h2 duration="15">Navigator</h2>!<h2>Page Objects</h2>!<h2 duration="5">Summary</h2>!

$('h2', duration: '5').size() == 2!

$('h2', text: 'Summary').size() == 1!

<h2 duration="5">Introduction</h2>!<h2 duration="15">Navigator</h2>!<h2>Page Objects</h2>!<h2 duration="5">Summary</h2>!

$('h2', text: contains('o')).size() == 2!

$('h2', text: iContains('o')).size() == 3!

$('h2', duration: contains('5')).size() == 3!

<div class="languages">!! ! <div class="language jvm">Java</div>!! ! <div class="language clr">C#</div>!! ! <div class="language jvm">Groovy</div>!! ! <div class="language clr">F#</div>!! ! <div class="language erlang">Elixir</div>!</div>

$('div.languages').find('.jvm').each{ element ->!! ! println element.text()!}

Java Groovy

<div class="languages">!! ! <div class="language jvm">Java</div>!! ! <div class="language clr">C#</div>!! ! <div class="language jvm">Groovy</div>!! ! <div class="language clr">F#</div>!! ! <div class="language erlang">Elixir</div>!</div>

$('.language').filter('.jvm').each{ element ->!! ! println element.text()!}

Java Groovy

$('.language').not('.clr').each{ element ->!! ! println element.text()!}

Java Groovy Elixir

Page Objects

Page Objects

Modules

Modules

Modulesclass Record extends Module{!! static content = {!! ! column {index -> $('td', index)}!! ! productCode {column(1).text()}!! ! price { column(2).text().toInteger()}!! }!}

class ProductPage extends Page{!! static url = 'table.html'!! static content = {!! ! products {moduleList Record, $('table tbody tr')}!! }!}

Modules

Browser.drive() {!! to ProductPage!! products.each{ product ->!! ! println "${product.productCode} -> ${product.price}"!! }!}.quit()

Modules List

Waiting

Wait<div id="dynamic"></div>

waitFor { $('#dynamic').text()}!waitFor(8) { $('#dynamic').text()}!waitFor(8, 0.5) { $('#dynamic').text()}!waitFor('slow') { $('#dynamic').text()}

// GebConfig.groovy!waiting {! presets {! slow {! timeout = 12! retryInterval = 1! }! }!}

Integration

https://www.flickr.com/photos/lumaxart/2137737248

Supported Frameworks

@Stepwise!class SampleGebSpec extends GebReportingSpec{!! def "User can login"(){! !! when:! !! ! to LoginPage!! ! ! login('user1', 'secret')! ! ! then:!! ! ! at DashboardPage!! ! ! and:!! ! ! header.pageTitle == 'Dashboard'! }!!}!

Spock Example

Integration

• Power of WebDriver • Elegance of jQuery selection • Robustness of Page Object

modeling • Expressiveness of Groovy

Summary

Welcome Geb

ReferencesOfficial Geb Page - http://www.gebish.org/ !Example - https://github.com/geb/geb-example-gradle !Spock Documentation - http://spock-framework.readthedocs.org/en/latest/ !Code samples - https://github.com/naresha/seconf2014

Recommended