geb for testing your grails application

74
GEB FOR TESTING YOUR GRAILS APPLICATION Jacob Aae Mikkelsen

Upload: jacobaae

Post on 10-Aug-2015

36 views

Category:

Software


5 download

TRANSCRIPT

Page 1: Geb for testing your grails application

GEB FOR TESTING YOUR GRAILSAPPLICATION

Jacob Aae Mikkelsen

Page 2: Geb for testing your grails application

AGENDAFunctional testing

Geb - cudos and history

How Geb works

Geb and Grails 2 and 3

Browser support

Javascript

Page 3: Geb for testing your grails application

JACOB AAE MIKKELSENSenior Engineer at Lego

Microservice based architechture on JVM

Previously 4 years at Gennemtænkt IT

Consultant on Groovy and Grails

External Associate Professor - University of SouthernDenmark

@JacobAae

Blogs The Grails Diary

Page 4: Geb for testing your grails application

FUNCTIONAL TESTINGIgnores the specifics of the underlying softwarecomponent under test.

Merely asserts that providing certain input results incertain output.

Web-application: Programmatically controlling a webbrowser to simulate the actions of a user on a web page.

Traditionally been tedious, cumbersome and brittleto do

Geb helps ease the pain

Page 5: Geb for testing your grails application

GEB

Page 6: Geb for testing your grails application

CREDITSLuke Daley

Marcin Erdmann

Page 7: Geb for testing your grails application

GEB HISTORYStarted in November 2009

Created by Luke Daley

Current project lead Marcin Erdman

Page 8: Geb for testing your grails application

WHY GEBjQuery like selector syntax

Power of WebDriver (Easier api)

Robustness of Page Object modeling

Expressiveness of the Groovy language

Integrates well with build systems (Gradle/Maven)

Excellent user manual/documentation

Page 9: Geb for testing your grails application

GEB IMPLEMENTATIONBuild on top of the WebDriver browser automation library

successor to the Selenium Remote Control (RC) testingframework.

Selenium RC → JavaScript to interact

WebDriver → native browser drivers

Use JUnit or Spock

Page 10: Geb for testing your grails application

USING GEB

Page 11: Geb for testing your grails application

GEB SELECTORS (1)Jquery like syntax

// match all 'p' elements on page$("p")

// match the first 'p' element on the page$("p", 0)

// All 'p' elements with a title value 'section'$("div", title: "section")

// match the first 'p' element title attribute 'section'$("p", 0, title: "section")

// match the first 'p' element with the class 'main'$("p.main", 0)

Page 12: Geb for testing your grails application

GEB SELECTORS (2)Selecting returns Navigator objects

// The parent of the first div$("div", 0).parent()

// All tables with a cellspacing// attribute value of 0 that are nested in a paragraph$("p").find("table", cellspacing: '0')

Page 13: Geb for testing your grails application

RETRIVING INFORMATION$("p").text() == "a"$("p").tag() == "p"$("p").@title == "a"$("p").classes() == ["a", "para"]

Page 14: Geb for testing your grails application

INTERACTION WITH CONTENTclick()

isDisplayed()

withConfirm

withAlert

$("a.btn").click()$("div").isDisplayed()

withConfirm $("button.delete").click()

Page 15: Geb for testing your grails application

SENDING INPUTimport org.openqa.selenium.Keys

// Shorthand for sendKeys() method of WebDriver.$("div") << "abc"

$("input", name: "foo") << Keys.chord(Keys.CONTROL, "c")

Page 16: Geb for testing your grails application

MORE INTERACTION WITH FORMSConsider the following HTML…

<form> <input type="text" name="geb" value="Functional" /></form>

The value can be read and written via property notation…

$("form").geb == "Functional"$("form").geb = "Testing"$("form").geb == "Testing"

These are literally shortcuts for…

$("form").find("input", name: "geb").value() == "Functional"$("form").find("input", name: "geb").value("Testing")$("form").find("input", name: "geb").value() == "Testing"

Page 17: Geb for testing your grails application

VARIABLES AVAILABLEtitle

browser

currentUrl

currentWindow

Page 18: Geb for testing your grails application

MORE POSSIBILITIESUploading files

Interaction closures

Simulate drag-n-drop

Control-clicking

Interacting with javascript

js object

Page 19: Geb for testing your grails application

STRUCTURING GEB TESTSLets test a CRUD part of a grails application registrering

conference attendees

Lets test the following

1. Goto list of attendees page

2. Create new employee (incl. invalid data once)

3. Update the employee

4. Check data is updated

Page 20: Geb for testing your grails application

GEB SPEC BASICSimport geb.spock.GebSpec

@Stepwise // Ensures the tests are run sequentiallyclass AttendeeFunctionalSpec extends GebSpec

// Spock specs here

Page 21: Geb for testing your grails application

GEB SPEC (1)The naive inmaintainable way!

void "Go to list page ­ check initial state"() when:"The home page is visited" go '/attendee/index'

then: title == "Attendee List"

Page 22: Geb for testing your grails application

GEB SPEC (2)The naive inmaintainable way!

void "Click new attendee button"() when: $("a.create").click()

then: title == "Create Attendee"

Page 23: Geb for testing your grails application

GEB SPEC (3)The naive inmaintainable way!

void "Submit form with errors"() when: $("button.btn­primary").click()

then: title == "Create Attendee"

Page 24: Geb for testing your grails application

GEB SPEC (4)The naive inmaintainable way!

void "Submit form with no errors"() when: $('form').name = 'Bobby' $('form').email = '[email protected]'

and: $("button.btn­primary").click()

then: title == 'Show Attendee' $('span.property­value').find it.text() == 'Bobby' $('span.property­value').find it.text() == '[email protected]'

Page 25: Geb for testing your grails application

GEB SPEC (5)The naive inmaintainable way!

void "Click Edit Button"() when: $("a.btn­primary").click()

then: title == 'Edit Attendee'

Page 26: Geb for testing your grails application

GEB SPEC (6)The naive inmaintainable way!

void "Update Attendee"() when: $('form').name = 'Alison' $('form').email = '[email protected]'

and: $("button.btn­primary").click()

then: title == 'Show Attendee' $('span.property­value').find it.text() == 'Alison' $('span.property­value').find it.text() == '[email protected]'

Page 27: Geb for testing your grails application

GEB SPEC - THE BETTER WAYIf we make a few scenarios, there will be

Much duplication

Many places to correct if we change the layout / DOM

We can correct this using pages and modules

Page 28: Geb for testing your grails application

PAGE OBJECTSDescribes a web page

Url

How to check if we are at the correct place

Content we wish to interact with

Page 29: Geb for testing your grails application

PAGE OBJECTSimport eu.gr8conf.grailsdemo.modules.NavigationBarModuleimport geb.Page

class AttendeeShowPage extends Page

static url = "/attendee/show"

static at = title ==~ /Show Attendee/

static content = attProp $('span.property­label') name attProp.find it.text() == 'Name'.next().text() email attPro.find it.text() == 'Email'.next().text() editButton $("a.btn­primary")

Page 30: Geb for testing your grails application

MODULESDescribes repeated content

Across pages

Within the same page

Page 31: Geb for testing your grails application

MODULESimport geb.Module

class NavigationBarModule extends Module

static base = $('nav.navbar')

static content = home(required: false) $('a.home') listAttendee(required: false) $('a.list') newAttendee(required: false) $('a.create')

Page 32: Geb for testing your grails application

MODULESstatic content = // Like this, the module does not need a base// form module NavigationBarModule, $('nav.navbar') form module NavigationBarModule

Page 33: Geb for testing your grails application

MODULE FOR REPEATED CONTENTIN A PAGE

import geb.Module

class AttendeeListItemModule extends Module

static content = data $("td", it) name data(0).text() email data(1).text() nationality data(2).text() dateCreated data(3).text() lastUpdated data(4).text()

Page 34: Geb for testing your grails application

MODULE FOR REPEATED CONTENTIN A PAGE

AttendeeListPage.groovy

static content = menubar module NavigationBarModule attendees moduleList AttendeeListItemModule, $("table tr").tail()

Page 35: Geb for testing your grails application

MODULE FOR REPEATED CONTENTIN A PAGE

when:to AttendeeListPage

then:attendees*.name.contains('Guillaume Laforge')

Page 36: Geb for testing your grails application

GEB SPEC - STRUCTURED (1)Lets try to restructure the ugly spec from before

void "Go to list page ­ check initial state"() when: to AttendeeIndexPage

then: at AttendeeIndexPage

Page 37: Geb for testing your grails application

GEB SPEC - STRUCTURED (2)void "Click new attendee button"() when: menubar.newAttendee.click()

then: at AttendeeCreatePage

Page 38: Geb for testing your grails application

GEB SPEC - STRUCTURED (3)void "Submit form with errors"() when: submitButton.click()

then: at AttendeeCreatePage

Page 39: Geb for testing your grails application

GEB SPEC - STRUCTURED (4)void "Submit form with no errors"() when: form.name = 'Bob' form.email = '[email protected]'

and: submitButton.click()

then: at AttendeeShowPage name == 'Bob' email == '[email protected]'

Page 40: Geb for testing your grails application

GEB SPEC - STRUCTURED (5)void "Click Edit Button"() when: editButton.click()

then: at AttendeeEditPage

Page 41: Geb for testing your grails application

GEB SPEC - STRUCTURED (6)void "Update Attendee"() when: form.name = 'Alice' form.email = '[email protected]'

and: updateButton.click()

then: at AttendeeShowPage title == 'Show Attendee' name == 'Alice' email == '[email protected]'

Page 42: Geb for testing your grails application

GEB WITH GRAILS

Page 43: Geb for testing your grails application

GEB AND GRAILS 2.XMust install plugin in BuildConfig.groovy

dependencies ... test("org.seleniumhq.selenium:selenium­support:2.45.0") test("org.seleniumhq.selenium:selenium­firefox­driver:2.45.0") test "org.gebish:geb­spock:0.10.0"plugins ... test "org.grails.plugins:geb:0.10.0"

Page 44: Geb for testing your grails application

GEB TESTS IN GRAILS 2.XTests placed in test/functional folder

Running the tests

grails test­app functional:

Page 45: Geb for testing your grails application

GEB AND GRAILS 3Geb is default in build.gradle

dependencies ... testCompile "org.grails.plugins:geb"

// Note: It is recommended to update to a more robust driver // (Chrome, Firefox etc.) testRuntime 'org.seleniumhq.selenium:selenium­htmlunit­driver:2.44.0

Page 46: Geb for testing your grails application

GEB TESTS IN GRAILS 3Creating Geb Spec

grails create­functional­test MyGebScenario

Placing the test in src/integration-test/groovy

Running the tests

grails test­app ­integration

Page 47: Geb for testing your grails application

GENERATED CLASS@Integration@Rollbackclass ManyAttendeesSpec extends GebSpec

void "test something"() when:"The home page is visited" go '/'

then:"The title is correct" $('title').text() == "Welcome to Grails"

Page 48: Geb for testing your grails application

INTERACTING WITH APPLICATIONWhen some functionality is needed that is not exposed

through the browser, it can be necessary to interact with theapplication under test.

Page 49: Geb for testing your grails application

GRAILS 2.5Tests not running in same JVM

Done with remote-control plugin

Send a closure for execution in application

compile ":remote­control:2.0"

Page 50: Geb for testing your grails application

REMOTE CONTROLsetup: 'Create some item not available through GUI'def id = remote Item item = new Item(name: "MyItem") item.save() item.id

Page 51: Geb for testing your grails application

GRAILS 3.0Application is in same jvm

Interaction is possible directly

Tests run more like integration tests

Page 52: Geb for testing your grails application

INTERACTING WITH APPLICATIONvoid "Test Pagination is shown with 15 attendees"() setup: Attendee.withNewTransaction 15.times new Attendee(name: "N$it", email: "[email protected]").save()

when: to AttendeeIndexPage

then: hasPagination()

Page 53: Geb for testing your grails application

INTERACTING WITH APPLICATIONstatic content = menubar module NavigationBarModule pagination(required: false) $('span.currentStep')

boolean hasPagination() pagination.text()

Page 54: Geb for testing your grails application

CONFIGURATION AND BROWSERSUPPORT

Page 55: Geb for testing your grails application

GEBCONFIGConfiguration for Geb is placed in GebConfig.groovy

In Grails 3, place it in ´src/integration-test/groovy`

http://www.gebish.org/manual/current/configuration.html

Page 56: Geb for testing your grails application

DRIVERIt is possible to configure the browser used.

build.gradle

compile 'org.seleniumhq.selenium:selenium­chrome­driver:2.45.0'compile 'org.seleniumhq.selenium:selenium­firefox­driver:2.45.0'

Page 57: Geb for testing your grails application

FIREFOXGebConfig.groovy

import org.openqa.selenium.firefox.FirefoxProfileimport org.openqa.selenium.firefox.FirefoxDriver

driver = FirefoxProfile profile = new FirefoxProfile() profile.setPreference("browser.download.folderList", 2) profile.setPreference("browser.download.dir", "/tmp") profile.setPreference( "browser.helperApps.neverAsk.saveToDisk", "text/csv")

def driverInstance = new FirefoxDriver(profile) driverInstance.manage().window().maximize() driverInstance

Page 58: Geb for testing your grails application

CHROMENeeds ChromeDriver downloaded

Pretty fast and stable

Page 59: Geb for testing your grails application

CHROME (1)GebConfig.groovy

private String driverLocationDependingOnOperatingSystem() String os = System.getProperty("os.name").toLowerCase(); def loc = "http://chromedriver.storage.googleapis.com/2.15" if( os.contains('mac')) return "$loc/chromedriver_mac32.zip" if( os.contains('win')) return "$loc/chromedriver_win32.zip" return "$loc/chromedriver_linux64.zip"

Page 60: Geb for testing your grails application

CHROME (2)GebConfig.groovy

private void downloadDriver(File file, String path) if (!file.exists()) def ant = new AntBuilder() ant.get(src: path, dest: 'driver.zip') ant.unzip(src: 'driver.zip', dest: file.parent) ant.delete(file: 'driver.zip') ant.chmod(file: file, perm: '700')

Page 61: Geb for testing your grails application

CHROME (3)GebConfig.groovy

def chromeDriver = new File('build/drivers/chrome/chromedriver')downloadDriver(chromeDriver, driverLocationDependingOnOperatingSystem())System.setProperty('webdriver.chrome.driver', chromeDriver.absolutePath)

driver = def driverInstance = new ChromeDriver()

def browserWindow = driverInstance.manage().window() // width, height browserWindow.size = new Dimension(1000, 2500) browserWindow.position = new Point(0, 0)

driverInstance

Page 62: Geb for testing your grails application

WAITINGGebConfig.groovy

waiting timeout = 10 retryInterval = 0.5

baseNavigatorWaiting = trueatCheckWaiting = true

Page 63: Geb for testing your grails application

USING WAITING<div class="fade­me­in" style="display: none"> Hi ­ are yo waiting for me?</div><script> $('div.fade­me­in').delay(3000).slideDown();</script>

static content = fadeInMessage $('div.fade­me­in')

then:waitFor fadeInMessage.text() == 'Hi ­ are yo waiting for me?'

Page 64: Geb for testing your grails application

REPORTING

Page 65: Geb for testing your grails application

TEST REPORTSNicely formatted

Spock power-assert format

Page 66: Geb for testing your grails application

SCREENSHOTSScreenshots and HTML from end of each test:

Extend from GebReportingSpec

class AttendeeFunctionalSpec extends GebReportingSpec

GebConfig.groovy

reportsDir = new File("build/geb­reports")

Page 67: Geb for testing your grails application

AD-HOC SCREENSHOTSreport "When­form­is­just­filled"

Saves a report in reportsDir

Numbered in increasing order

Page 68: Geb for testing your grails application

JAVASCRIPTIn case you need to interact using javascript

Page 69: Geb for testing your grails application

EXECUTING JAVASCRIPTClicking a button that is hidden will create a

ElementNotVisibleException

<fieldset class="well" style="display: none"> <g:link class="btn" action="index">List</g:link></fieldset>

Page 70: Geb for testing your grails application

EXECUTING JAVASCRIPTJavascriptExecutor executor = (JavascriptExecutor) driverexecutor.executeScript('jQuery(".well").show();')

Page 71: Geb for testing your grails application

WRAPPING JAVASCRIPTdef js( String script ) (driver as JavascriptExecutor).executeScript( script )

js('jQuery(".well").show();')

Page 72: Geb for testing your grails application

OTHER USAGESScreenscraping of a site

Solving complex problems like 2048

Page 73: Geb for testing your grails application

RESOURCEShttp://gebish.org

https://github.com/geb

https://gist.github.com/melix/9619800

https://fbflex.wordpress.com/2010/08/25/geb-and-grails-tips-tricks-and-gotchas/

https://github.com/JacobAae/eu-gr8conf-grailsdemo

Page 74: Geb for testing your grails application

QUESTIONS?