SlideShare a Scribd company logo
1 of 54
Download to read offline
Geb Best Practices
Marcin Erdmann
@marcinerdmann
•  Groovy enthusiast since 2010
•  Geb user since 2011
•  Geb lead since 2014
•  Open source contributor
•  Testing junkie
1.0!!!
08.10.2016
50 Geb contributors
•  Robert Fletcher
•  Peter Niederwieser
•  Alexander Zolotov
•  Christoph Neuroth
•  Antony Jones
•  Jan-Hendrik Peters
•  Tomás Lin
•  Jason Cahoon
•  Tomasz Kalkosiński
•  Rich Douglas Evans
•  Ian Durkan
•  Colin Harrington
•  Bob Herrmann
•  George T Walters II
•  Craig Atkinson
•  Andy Duncan
•  John Engelman
•  Michael Legart
•  Graeme Rocher
•  Craig Atkinson
•  Ken Geis
•  Chris Prior
•  Kelly Robinson
•  Todd Gerspacher
•  David M. Carr
•  Tom Dunstan
•  Brian Kotek
•  David W Millar
•  Ai-Lin Liou
•  Varun Menon
•  Anders D. Johnson
•  Hiroyuki Ohnaka
•  Erik Pragt
•  Vijay Bolleypally
•  Pierre Hilt
•  Yotaro Takahashi
•  Jochen Berger
•  Matan Katz
•  Victor Parmar
•  Berardino la Torre
•  Markus Schlichting
•  Andrey Hitrin
•  Leo Fedorov
•  Chris Byrneham
•  Aseem Bansal
•  Tomasz Przybysz
•  Brian Stewart
•  Jacob Aae Mikkelsen
•  Patrick Radtke
•  Leonard Brünings
Breaking changes in 1.0
•  Methods like isDisplayed() and
text() throw an exception when called
on multi element navigators
•  Weakly typed module() and
moduleList() removed
•  isDisabled() and isReadOnly()
removed from Navigator
Heresy warning...
Advanced usage
a.k.a. Tips & Tricks
Module is-a Navigator
•  Modules wrap around their base
Navigator
•  All Navigator methods can be called on
Module instances
•  Navigator methods can be used in
module implementations
Module is-a Navigator
<html>
<form method="post" action="login">
...
</from>
</html>
class LoginFormModule extends Module {
static base = { $("form") }
}

class LoginPage extends Page {
static content = {
form { module LoginFormModule }
}
}
Module is-a Navigator
to LoginPage
assert form.@method == "post”
assert form.displayed
Overriding value() on module
Class DatepickerModule extends Module {
LocalDate value() {
...
}

Navigator value(LocalDate date) {
...
}
}

class DatepickerPage extends Page {
static content = {
date { module DatepickerModule }
}
}
Overriding value() on module
to DatepickerPage
date.value(LocalDate.of(2017, 4, 1))
assert date.value() == LocalDate.of(2017, 4, 1)
to DatepickerPage
date = LocalDate.of(2017, 4, 1) 
assert date == LocalDate.of(2017, 4, 1)
Advanced navigation and types
•  Page.convertToPath(Object[]) is
used to translate arguments passed to
Browser.to() into a path
•  Consider overloading convertToPath()
for more expressive navigation
Advanced navigation and types
class PostPage extends Page {
static url = “posts”

String convertToPath(Post post) {
“${post.id}/${post.title.toLowerCase().replaceAll(“ ”, “-”)}”
}
}

def post = new Post(id: 1, title: “My first post”)

to PostPage, post
assert title == post.title
Parameterised pages
•  Pages can be instantiated and passed to
via(), to() and at()
•  Useful when you need to differ
implementation based on the object
represented by the page
Parameterised pages navigation
class PostPage extends Page {
Post post

String getPageUrl() {
“posts/${post.id}/${post.title.toLowerCase().replaceAll(“ ”, “-”)}”
}
}

def post = new Post(id: 1, title: “My first post”)

to(new PostPage(post: post))
assert title == post.title
Navigators are iterable
•  Navigators are backed by a collection of
WebElements
•  Navigators implement
Iterable<Navigator>
Navigators are iterable
<html>
<p>First paragraph</p>
<p>Second paragraph</p>
</html>
$(“p”).text() // throws exception
$(“p”)[0].text() // returns “First paragraph”
$(“p”)*.text() // returns [“First paragraph”, “Second paragraph”]

//returns [0: “First paragraph”, 1: “Second paragraph”]
$(“p”).withIndex().collectEntries { [(it.second): it.first.text()] }
What’s onLoad() for?
class CookieBarPage extends Page {
boolean autoCloseCookieBar = true
static content = {
cookieBar { module(CookieBarModule) }
}
void onLoad(Page previousPage) {
if (autoCloseCookieBar && cookieBar) {
cookieBar.close()
}
}

}
Injecting javascript into page
js.exec '''
var url = 'https://code.jquery.com/jquery-3.2.1.min.js';

var scriptElement = document.createElement('script');
scriptElement.setAttribute('src', url);
document.head.appendChild(scriptElement);
'''
Navigator’s elements in js
void waitForCssTransition(Navigator navigator, WaitingSupport waiting, JavascriptInterface js,
Closure trigger) {
js.exec(navigator.singleElement(), '''
var o = jQuery(arguments[0]);
window.setTransitionFinishedClass = function() {
$(this).addClass('transitionFinished');
}
o.bind('transitionend', window.setTransitionFinishedClass);
''')
try {
trigger.call()
waiting.waitFor { hasClass('transitionFinished') }
} finally {
js.exec(navigator.singleElement, '''
var o = jQuery(arguments[0]);
o.unbind('transitionend', window.setTransitionFinishedClass);
o.removeClass('transitionFinished')
window.setTransitionFinishedClass = undefined;
''')
}
}
Alternatives to inheritance
•  Using inheritance for code sharing leads to
complex inheritance structures
•  @Delegate can be used for code sharing
via delegation
•  Traits can be used for code sharing
Alternatives to inheritance
class TransitionSupport {
private final Navigator navigator
private final WaitingSupport waiting
private final JavascriptInterface js

TransitionSupport(Navigator navigator, WaitingSupport waiting, JavascriptInterface js) {
...
}
void waitForCssTransition(Closure trigger) {
...
}
}

class TransitioningModule extends Module {
@Delegate
TransitionSupport transitionSupport = new TransitionSupport(this, this, js)
}
Alternatives to inheritance
trait TransitionSupport implements Navigator, WaitingSupport {
abstract JavascriptInterface getJs()

void waitForCssTransition(Closure trigger) {
...
}
}

class TransitioningModule extends Module implements TransitionSupport {
}
Dynamic base url
class RatpackApplicationGebSpec extends GebSpec {

def application = new GroovyRatpackMainApplicationUnderTest()
def setup() {
browser.baseUrl = application.address.toString()
}

}
Testing responsive apps
class TestsMobileViewExtension extends 
AbstractAnnotationDrivenExtension<TestsMobileView> {
void visitFeatureAnnotation(TestsMobileView annotation, FeatureInfo feature) {
feature.addInterceptor { invocation ->
def window = new ConfigurationLoader().conf.driver.manage().window()
def originalSize = window.size
try {
window.size = new Dimension(320, 568)
invocation.proceed()
} finally {
window.size = originalSize
}
}
}
}
Best practices
a.k.a. Marcin’s musings
Strongly typed Geb code
•  Better authoring, i.e. autocompletion
•  Better navigation, i.e. going to method
definition, finding usages
•  Refactoring support
What IntelliJ understands?
•  Delegation to Browser methods in specs
•  Delegation to Page methods in specs
•  Content definitions
Tracking current page type
•  Capture current page in a variable
•  Use return values of via(), to() and
at()
•  Return new page instance from methods
triggering page transitions
Tracking current page
def homePage = to HomePage

homePage.loginPageLink.click()
def loginPage = at LoginPage

def securePage = loginPage.login("user", "password")
Tracking current page
to(HomePage).loginPageLink.click()

def securePage = at(LoginPage).login("user", "password")
At checks
•  Keep them quick and simple
•  Check if you are at the right page
•  Don’t test any page logic
What’s missing here?
class CookieBarPage extends Page {
boolean autoCloseCookieBar = true
static content = {
cookieBar { $('.cookie-message’) }
cookieBarText { $('.cookie-message-text').text() }
cookieBarCloseButton { $('.cookie-message-button > input') }
}

}
What are modules good for?
•  More than reuse
•  Modeling logical components
•  Hiding component structure from tests
•  Hiding complex interactions from tests
Invest time in fixture builders
•  Aim for easy, expressive and flexible data
setup
•  Keep data setup close to tests
•  Setup only the data necessary for the test
•  Groovy Remote Control can be very helpful
•  Fixtures are not not only about data
Geb’s test harness html fixture
def “can access element classes”() {
given:
html {
div(id: "a", 'class': "a1 a2 a3")
div(id: "b", 'class': "b1”)
}

expect:
$("#a").classes() == ["a1", "a2", "a3"]
$("#b").classes() == ["b1”]
}
Example data fixture DSL
bootstrapper.post {
id = “69f10bb6-118e-11e7-93ae-92361f002671”
title = “My first post”
tags = [“Groovy”, “Geb”]
author {
firstName = “Marcin”
lastName = “Erdmann”
}
}
Use real browser in CI
•  Available headless drivers are either
limited, not developed anymore or not
properly tested
•  Use a real browser with a virtual frame
buffer, i.e. Xvfb
•  Use a cloud browser provider
reportOnTestFailuresOnly
To waitFor() or
not?
To waitFor() or not?
•  Ask yourself if action is asynchronous
•  Watch out for quick asynchronous events
waitFor() considered harmful
•  Best not used directly in tests
•  Hide asynchronous behaviour in action
methods on modules and pages
Increasing the
timeout is
(usually) not the
answer
Use wait presets
Browser test are costly!
•  Slow, hard to maintain and flakey
•  Mind what you test at such high level
•  ...but they provide a lot of confidence
Cross browser
tests are costlier
Cloud browser providers
•  Gradle plugins for driving browsers with
Geb in BrowserStack and Suace Labs
•  Can test applications via a tunnel which are
not available on the Internet
Using attributes map selectors
•  Map selectors are now translated to CSS
attribute selectors
•  As quick as using css selectors but reads
better especially when using dynamic
values
Using attributes map selectors
$(‘button’, type: ‘select’)
$(‘button[type=“select”]’)

$(itemtype: ‘http://schema.org/Person’)
$(‘[itemtype=“http://schema.org/Person”]’)
Selecting by text is slow!
•  Selecting by text is a Geb extension not
something that CSS supports
•  Narrow down selected elements as much
as possible when selecting by text
Questions?
Thank you!

More Related Content

What's hot

Enhancing drone application development using python and dronekit
Enhancing drone application development using python and dronekitEnhancing drone application development using python and dronekit
Enhancing drone application development using python and dronekitDony Riyanto
 
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Edureka!
 
Google chrome extension
Google chrome extensionGoogle chrome extension
Google chrome extensionJohnny Kingdom
 
Introduction to Javascript By Satyen
Introduction to Javascript By  SatyenIntroduction to Javascript By  Satyen
Introduction to Javascript By SatyenSatyen Pandya
 
Customising QGroundControl
Customising QGroundControlCustomising QGroundControl
Customising QGroundControlGodfrey Nolan
 
Introduction to Python programming
Introduction to Python programmingIntroduction to Python programming
Introduction to Python programmingDamian T. Gordon
 
Web develop in flask
Web develop in flaskWeb develop in flask
Web develop in flaskJim Yeh
 
Complete Lecture on Css presentation
Complete Lecture on Css presentation Complete Lecture on Css presentation
Complete Lecture on Css presentation Salman Memon
 
Angular - Chapter 5 - Directives
 Angular - Chapter 5 - Directives Angular - Chapter 5 - Directives
Angular - Chapter 5 - DirectivesWebStackAcademy
 
JavaScript
JavaScriptJavaScript
JavaScriptSunil OS
 
Webinar: PHP and MySQL - Server-side Scripting Language for Web Development
Webinar: PHP and MySQL - Server-side Scripting Language for Web Development  Webinar: PHP and MySQL - Server-side Scripting Language for Web Development
Webinar: PHP and MySQL - Server-side Scripting Language for Web Development Edureka!
 
Drone Surveillance System: The Complete Setup Guide
Drone Surveillance System: The Complete Setup GuideDrone Surveillance System: The Complete Setup Guide
Drone Surveillance System: The Complete Setup GuideFlytBase
 

What's hot (20)

Enhancing drone application development using python and dronekit
Enhancing drone application development using python and dronekitEnhancing drone application development using python and dronekit
Enhancing drone application development using python and dronekit
 
Flask-Python
Flask-PythonFlask-Python
Flask-Python
 
Tomcat server
 Tomcat server Tomcat server
Tomcat server
 
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
 
Google chrome extension
Google chrome extensionGoogle chrome extension
Google chrome extension
 
Javascript
JavascriptJavascript
Javascript
 
Java script
Java scriptJava script
Java script
 
JUnit 4
JUnit 4JUnit 4
JUnit 4
 
Introduction to Javascript By Satyen
Introduction to Javascript By  SatyenIntroduction to Javascript By  Satyen
Introduction to Javascript By Satyen
 
jQuery PPT
jQuery PPTjQuery PPT
jQuery PPT
 
Customising QGroundControl
Customising QGroundControlCustomising QGroundControl
Customising QGroundControl
 
Introduction to Python programming
Introduction to Python programmingIntroduction to Python programming
Introduction to Python programming
 
Web develop in flask
Web develop in flaskWeb develop in flask
Web develop in flask
 
Complete Lecture on Css presentation
Complete Lecture on Css presentation Complete Lecture on Css presentation
Complete Lecture on Css presentation
 
Typescript ppt
Typescript pptTypescript ppt
Typescript ppt
 
Angular - Chapter 5 - Directives
 Angular - Chapter 5 - Directives Angular - Chapter 5 - Directives
Angular - Chapter 5 - Directives
 
JavaScript
JavaScriptJavaScript
JavaScript
 
C# Basics
C# BasicsC# Basics
C# Basics
 
Webinar: PHP and MySQL - Server-side Scripting Language for Web Development
Webinar: PHP and MySQL - Server-side Scripting Language for Web Development  Webinar: PHP and MySQL - Server-side Scripting Language for Web Development
Webinar: PHP and MySQL - Server-side Scripting Language for Web Development
 
Drone Surveillance System: The Complete Setup Guide
Drone Surveillance System: The Complete Setup GuideDrone Surveillance System: The Complete Setup Guide
Drone Surveillance System: The Complete Setup Guide
 

Similar to Geb Best Practices

jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)Doris Chen
 
Building Single-Page Web Appplications in dart - Devoxx France 2013
Building Single-Page Web Appplications in dart - Devoxx France 2013Building Single-Page Web Appplications in dart - Devoxx France 2013
Building Single-Page Web Appplications in dart - Devoxx France 2013yohanbeschi
 
Whats new in MongoDB 24
Whats new in MongoDB 24Whats new in MongoDB 24
Whats new in MongoDB 24MongoDB
 
Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2Somkiat Khitwongwattana
 
Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...
Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...
Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...mfrancis
 
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java PlatformMicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java PlatformMike Croft
 
Examiness hints and tips from the trenches
Examiness hints and tips from the trenchesExaminess hints and tips from the trenches
Examiness hints and tips from the trenchesIsmail Mayat
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyMark Proctor
 
Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?ACA IT-Solutions
 
5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)Christian Rokitta
 
Annotation processing and code gen
Annotation processing and code genAnnotation processing and code gen
Annotation processing and code genkoji lin
 
LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017Matthew Beale
 
node-crate: node.js and big data
 node-crate: node.js and big data node-crate: node.js and big data
node-crate: node.js and big dataStefan Thies
 
CouchDB for Web Applications - Erlang Factory London 2009
CouchDB for Web Applications - Erlang Factory London 2009CouchDB for Web Applications - Erlang Factory London 2009
CouchDB for Web Applications - Erlang Factory London 2009Jason Davies
 
DSL's with Groovy
DSL's with GroovyDSL's with Groovy
DSL's with Groovypaulbowler
 
Advanced guide to develop ajax applications using dojo
Advanced guide to develop ajax applications using dojoAdvanced guide to develop ajax applications using dojo
Advanced guide to develop ajax applications using dojoFu Cheng
 
Digital Publishing for Scale: The Economist and Go
Digital Publishing for Scale: The Economist and GoDigital Publishing for Scale: The Economist and Go
Digital Publishing for Scale: The Economist and GoC4Media
 
Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Eugenio Minardi
 

Similar to Geb Best Practices (20)

jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
Building Single-Page Web Appplications in dart - Devoxx France 2013
Building Single-Page Web Appplications in dart - Devoxx France 2013Building Single-Page Web Appplications in dart - Devoxx France 2013
Building Single-Page Web Appplications in dart - Devoxx France 2013
 
Whats new in MongoDB 24
Whats new in MongoDB 24Whats new in MongoDB 24
Whats new in MongoDB 24
 
Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2
 
Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...
Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...
Modularity and Domain Driven Design - A killer combination - T De Wolf & S va...
 
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java PlatformMicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
 
Examiness hints and tips from the trenches
Examiness hints and tips from the trenchesExaminess hints and tips from the trenches
Examiness hints and tips from the trenches
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
 
Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?
 
5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)
 
Annotation processing and code gen
Annotation processing and code genAnnotation processing and code gen
Annotation processing and code gen
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017
 
node-crate: node.js and big data
 node-crate: node.js and big data node-crate: node.js and big data
node-crate: node.js and big data
 
CouchDB for Web Applications - Erlang Factory London 2009
CouchDB for Web Applications - Erlang Factory London 2009CouchDB for Web Applications - Erlang Factory London 2009
CouchDB for Web Applications - Erlang Factory London 2009
 
DSL's with Groovy
DSL's with GroovyDSL's with Groovy
DSL's with Groovy
 
Life outside WO
Life outside WOLife outside WO
Life outside WO
 
Advanced guide to develop ajax applications using dojo
Advanced guide to develop ajax applications using dojoAdvanced guide to develop ajax applications using dojo
Advanced guide to develop ajax applications using dojo
 
Digital Publishing for Scale: The Economist and Go
Digital Publishing for Scale: The Economist and GoDigital Publishing for Scale: The Economist and Go
Digital Publishing for Scale: The Economist and Go
 
Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)
 

Recently uploaded

Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Sumanth A
 
Main Memory Management in Operating System
Main Memory Management in Operating SystemMain Memory Management in Operating System
Main Memory Management in Operating SystemRashmi Bhat
 
Engineering Drawing section of solid
Engineering Drawing     section of solidEngineering Drawing     section of solid
Engineering Drawing section of solidnamansinghjarodiya
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating SystemRashmi Bhat
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsResearcher Researcher
 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxRomil Mishra
 
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTESCME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTESkarthi keyan
 
Prach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism CommunityPrach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism Communityprachaibot
 
System Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingSystem Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingBootNeck1
 
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...Stork
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Romil Mishra
 
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdfDEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdfAkritiPradhan2
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionSneha Padhiar
 
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTIONTHE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTIONjhunlian
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptxmohitesoham12
 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsapna80328
 
Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfDrew Moseley
 
List of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdfList of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdfisabel213075
 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfChristianCDAM
 

Recently uploaded (20)

Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
 
Main Memory Management in Operating System
Main Memory Management in Operating SystemMain Memory Management in Operating System
Main Memory Management in Operating System
 
Engineering Drawing section of solid
Engineering Drawing     section of solidEngineering Drawing     section of solid
Engineering Drawing section of solid
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating System
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending Actuators
 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptx
 
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTESCME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
 
Prach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism CommunityPrach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism Community
 
System Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingSystem Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event Scheduling
 
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________
 
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdfDEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdf
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based question
 
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTIONTHE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptx
 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveying
 
Designing pile caps according to ACI 318-19.pptx
Designing pile caps according to ACI 318-19.pptxDesigning pile caps according to ACI 318-19.pptx
Designing pile caps according to ACI 318-19.pptx
 
Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdf
 
List of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdfList of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdf
 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdf
 

Geb Best Practices

  • 2. @marcinerdmann •  Groovy enthusiast since 2010 •  Geb user since 2011 •  Geb lead since 2014 •  Open source contributor •  Testing junkie
  • 3.
  • 5. 50 Geb contributors •  Robert Fletcher •  Peter Niederwieser •  Alexander Zolotov •  Christoph Neuroth •  Antony Jones •  Jan-Hendrik Peters •  Tomás Lin •  Jason Cahoon •  Tomasz Kalkosiński •  Rich Douglas Evans •  Ian Durkan •  Colin Harrington •  Bob Herrmann •  George T Walters II •  Craig Atkinson •  Andy Duncan •  John Engelman •  Michael Legart •  Graeme Rocher •  Craig Atkinson •  Ken Geis •  Chris Prior •  Kelly Robinson •  Todd Gerspacher •  David M. Carr •  Tom Dunstan •  Brian Kotek •  David W Millar •  Ai-Lin Liou •  Varun Menon •  Anders D. Johnson •  Hiroyuki Ohnaka •  Erik Pragt •  Vijay Bolleypally •  Pierre Hilt •  Yotaro Takahashi •  Jochen Berger •  Matan Katz •  Victor Parmar •  Berardino la Torre •  Markus Schlichting •  Andrey Hitrin •  Leo Fedorov •  Chris Byrneham •  Aseem Bansal •  Tomasz Przybysz •  Brian Stewart •  Jacob Aae Mikkelsen •  Patrick Radtke •  Leonard Brünings
  • 6. Breaking changes in 1.0 •  Methods like isDisplayed() and text() throw an exception when called on multi element navigators •  Weakly typed module() and moduleList() removed •  isDisabled() and isReadOnly() removed from Navigator
  • 9. Module is-a Navigator •  Modules wrap around their base Navigator •  All Navigator methods can be called on Module instances •  Navigator methods can be used in module implementations
  • 10. Module is-a Navigator <html> <form method="post" action="login"> ... </from> </html> class LoginFormModule extends Module { static base = { $("form") } } class LoginPage extends Page { static content = { form { module LoginFormModule } } }
  • 11. Module is-a Navigator to LoginPage assert form.@method == "post” assert form.displayed
  • 12. Overriding value() on module Class DatepickerModule extends Module { LocalDate value() { ... } Navigator value(LocalDate date) { ... } } class DatepickerPage extends Page { static content = { date { module DatepickerModule } } }
  • 13. Overriding value() on module to DatepickerPage date.value(LocalDate.of(2017, 4, 1)) assert date.value() == LocalDate.of(2017, 4, 1) to DatepickerPage date = LocalDate.of(2017, 4, 1) assert date == LocalDate.of(2017, 4, 1)
  • 14. Advanced navigation and types •  Page.convertToPath(Object[]) is used to translate arguments passed to Browser.to() into a path •  Consider overloading convertToPath() for more expressive navigation
  • 15. Advanced navigation and types class PostPage extends Page { static url = “posts” String convertToPath(Post post) { “${post.id}/${post.title.toLowerCase().replaceAll(“ ”, “-”)}” } } def post = new Post(id: 1, title: “My first post”) to PostPage, post assert title == post.title
  • 16. Parameterised pages •  Pages can be instantiated and passed to via(), to() and at() •  Useful when you need to differ implementation based on the object represented by the page
  • 17. Parameterised pages navigation class PostPage extends Page { Post post String getPageUrl() { “posts/${post.id}/${post.title.toLowerCase().replaceAll(“ ”, “-”)}” } } def post = new Post(id: 1, title: “My first post”) to(new PostPage(post: post)) assert title == post.title
  • 18. Navigators are iterable •  Navigators are backed by a collection of WebElements •  Navigators implement Iterable<Navigator>
  • 19. Navigators are iterable <html> <p>First paragraph</p> <p>Second paragraph</p> </html> $(“p”).text() // throws exception $(“p”)[0].text() // returns “First paragraph” $(“p”)*.text() // returns [“First paragraph”, “Second paragraph”] //returns [0: “First paragraph”, 1: “Second paragraph”] $(“p”).withIndex().collectEntries { [(it.second): it.first.text()] }
  • 20. What’s onLoad() for? class CookieBarPage extends Page { boolean autoCloseCookieBar = true static content = { cookieBar { module(CookieBarModule) } } void onLoad(Page previousPage) { if (autoCloseCookieBar && cookieBar) { cookieBar.close() } } }
  • 21. Injecting javascript into page js.exec ''' var url = 'https://code.jquery.com/jquery-3.2.1.min.js'; var scriptElement = document.createElement('script'); scriptElement.setAttribute('src', url); document.head.appendChild(scriptElement); '''
  • 22. Navigator’s elements in js void waitForCssTransition(Navigator navigator, WaitingSupport waiting, JavascriptInterface js, Closure trigger) { js.exec(navigator.singleElement(), ''' var o = jQuery(arguments[0]); window.setTransitionFinishedClass = function() { $(this).addClass('transitionFinished'); } o.bind('transitionend', window.setTransitionFinishedClass); ''') try { trigger.call() waiting.waitFor { hasClass('transitionFinished') } } finally { js.exec(navigator.singleElement, ''' var o = jQuery(arguments[0]); o.unbind('transitionend', window.setTransitionFinishedClass); o.removeClass('transitionFinished') window.setTransitionFinishedClass = undefined; ''') } }
  • 23. Alternatives to inheritance •  Using inheritance for code sharing leads to complex inheritance structures •  @Delegate can be used for code sharing via delegation •  Traits can be used for code sharing
  • 24. Alternatives to inheritance class TransitionSupport { private final Navigator navigator private final WaitingSupport waiting private final JavascriptInterface js TransitionSupport(Navigator navigator, WaitingSupport waiting, JavascriptInterface js) { ... } void waitForCssTransition(Closure trigger) { ... } } class TransitioningModule extends Module { @Delegate TransitionSupport transitionSupport = new TransitionSupport(this, this, js) }
  • 25. Alternatives to inheritance trait TransitionSupport implements Navigator, WaitingSupport { abstract JavascriptInterface getJs() void waitForCssTransition(Closure trigger) { ... } } class TransitioningModule extends Module implements TransitionSupport { }
  • 26. Dynamic base url class RatpackApplicationGebSpec extends GebSpec { def application = new GroovyRatpackMainApplicationUnderTest() def setup() { browser.baseUrl = application.address.toString() } }
  • 27. Testing responsive apps class TestsMobileViewExtension extends AbstractAnnotationDrivenExtension<TestsMobileView> { void visitFeatureAnnotation(TestsMobileView annotation, FeatureInfo feature) { feature.addInterceptor { invocation -> def window = new ConfigurationLoader().conf.driver.manage().window() def originalSize = window.size try { window.size = new Dimension(320, 568) invocation.proceed() } finally { window.size = originalSize } } } }
  • 29. Strongly typed Geb code •  Better authoring, i.e. autocompletion •  Better navigation, i.e. going to method definition, finding usages •  Refactoring support
  • 30. What IntelliJ understands? •  Delegation to Browser methods in specs •  Delegation to Page methods in specs •  Content definitions
  • 31. Tracking current page type •  Capture current page in a variable •  Use return values of via(), to() and at() •  Return new page instance from methods triggering page transitions
  • 32. Tracking current page def homePage = to HomePage homePage.loginPageLink.click() def loginPage = at LoginPage def securePage = loginPage.login("user", "password")
  • 33. Tracking current page to(HomePage).loginPageLink.click() def securePage = at(LoginPage).login("user", "password")
  • 34. At checks •  Keep them quick and simple •  Check if you are at the right page •  Don’t test any page logic
  • 35. What’s missing here? class CookieBarPage extends Page { boolean autoCloseCookieBar = true static content = { cookieBar { $('.cookie-message’) } cookieBarText { $('.cookie-message-text').text() } cookieBarCloseButton { $('.cookie-message-button > input') } } }
  • 36. What are modules good for? •  More than reuse •  Modeling logical components •  Hiding component structure from tests •  Hiding complex interactions from tests
  • 37. Invest time in fixture builders •  Aim for easy, expressive and flexible data setup •  Keep data setup close to tests •  Setup only the data necessary for the test •  Groovy Remote Control can be very helpful •  Fixtures are not not only about data
  • 38. Geb’s test harness html fixture def “can access element classes”() { given: html { div(id: "a", 'class': "a1 a2 a3") div(id: "b", 'class': "b1”) } expect: $("#a").classes() == ["a1", "a2", "a3"] $("#b").classes() == ["b1”] }
  • 39. Example data fixture DSL bootstrapper.post { id = “69f10bb6-118e-11e7-93ae-92361f002671” title = “My first post” tags = [“Groovy”, “Geb”] author { firstName = “Marcin” lastName = “Erdmann” } }
  • 40. Use real browser in CI •  Available headless drivers are either limited, not developed anymore or not properly tested •  Use a real browser with a virtual frame buffer, i.e. Xvfb •  Use a cloud browser provider
  • 43. To waitFor() or not? •  Ask yourself if action is asynchronous •  Watch out for quick asynchronous events
  • 44. waitFor() considered harmful •  Best not used directly in tests •  Hide asynchronous behaviour in action methods on modules and pages
  • 47. Browser test are costly! •  Slow, hard to maintain and flakey •  Mind what you test at such high level •  ...but they provide a lot of confidence
  • 49. Cloud browser providers •  Gradle plugins for driving browsers with Geb in BrowserStack and Suace Labs •  Can test applications via a tunnel which are not available on the Internet
  • 50. Using attributes map selectors •  Map selectors are now translated to CSS attribute selectors •  As quick as using css selectors but reads better especially when using dynamic values
  • 51. Using attributes map selectors $(‘button’, type: ‘select’) $(‘button[type=“select”]’) $(itemtype: ‘http://schema.org/Person’) $(‘[itemtype=“http://schema.org/Person”]’)
  • 52. Selecting by text is slow! •  Selecting by text is a Geb extension not something that CSS supports •  Narrow down selected elements as much as possible when selecting by text