SlideShare a Scribd company logo
1 of 108
Download to read offline
1
GEB FOR BROWSER
AUTOMATION
Jacob Aae Mikkelsen
AGENDA
Functional testing
Geb - cudos and history
How Geb works
Geb and Ratpack, Grails 2 and 3
Browser support
Tips and Tricks
2 . 1
JACOB AAE MIKKELSEN
Senior 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 Southern
Denmark
@JacobAae
Blogs The Grails Diary
2 . 23 . 1
FUNCTIONAL TESTING
3 . 2
WHY?
3 . 3
3 . 4
FUNCTIONAL TESTING
Ignores the specifics of the underlying so ware
component under test.
Whitebox / Greybox
Merely asserts that providing certain input results in
certain output.
Web-application: Programmatically controlling a web
browser to simulate the actions of a user on a web page.
3 . 5
BROWSER AUTOMATION
3 . 64 . 1
4 . 2
GEB HISTORY
Started in November 2009
Created by Luke Daley
Current project lead Marcin Erdman
GEB IMPLEMENTATION
Build on top of the WebDriver browser automation library
successor to the Selenium Remote Control (RC) testing
framework.
Selenium RC → JavaScript to interact
WebDriver → native browser drivers
Use JUnit or Spock
4 . 3
WEBDRIVER
Very active development
Stable API and feature set
Verbose
Low level
Not a complete solution
4 . 4
WHY GEB
jQuery 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
4 . 5
5 . 1
USING GEB
4 . 6
5 . 2
NAVIGATOR
The $()method returns a Navigator object
General format - Jquery like selecter syntax
$ ( < c s s s e l e c t o r > , < i n d e x / r a n g e > , < a t t r i b u t e / t e x t m a t c h e r s > )
GEB SELECTORS (1)
/ / m a t c h a l l ' p ' e l e m e n t s o n p a g e
$ ( " p " )
/ / m a t c h t h e f i r s t ' p ' e l e m e n t o n t h e p a g e
$ ( " p " , 0 )
/ / A l l ' d i v ' e l e m e n t s w i t h a t i t l e v a l u e ' s e c t i o n '
$ ( " d i v " , t i t l e : " s e c t i o n " )
/ / m a t c h t h e f i r s t ' d i v ' e l e m e n t t e x t ' s e c t i o n '
$ ( " d i v " , 0 , t e x t : " s e c t i o n " )
/ / m a t c h t h e f i r s t ' d i v ' e l e m e n t w i t h t h e c l a s s ' m a i n '
$ ( " d i v . m a i n " , 0 )
5 . 3
GEB SELECTORS (2)
Text attribute supports regex
/ / A n y d i v w i t h t h e t e x t s t a r t i n g w i h G R 8
$ ( " d i v " , t e x t : ~ / G R 8 . + / )
$ ( " p " , t e x t : s t a r t s W i t h ( " G R 8 " ) )
/ / A n d o t h e r h a n d y p r e d i c a t e s
$ ( " d i v " , c l a s s : c o n t a i n s ( " u i - " ) )
5 . 4
GEB SELECTORS (3)
Selecting returns Navigatorobjects
/ / T h e p a r e n t o f t h e f i r s t d i v
$ ( " d i v " , 0 ) . p a r e n t ( )
/ / A l l t a b l e s w i t h a c e l l s p a c i n g
/ / a t t r i b u t e v a l u e o f 0 t h a t a r e n e s t e d i n a p a r a g r a p h
$ ( " p " ) . f i n d ( " t a b l e " , c e l l s p a c i n g : ' 0 ' )
5 . 55 . 6
CSS SUPPORT
$ ( " t a b l e t r : n t h - c h i l d ( 2 n + 1 ) t d " )
RETRIVING INFORMATION
< p i d = " s a m p l e " c l a s s = " c l a s s - a c l a s s - b " t i t l e = " S a m p l e p e l e m e n t " >
S a m p l e t e x t
< / p >
$ ( " p " ) . t e x t ( ) = = " S a m p l e t e x t "
$ ( " # s a m p l e " ) . t a g ( ) = = " p "
$ ( " p " ) . @ t i t l e = = " S a m p l e p e l e m e n t "
$ ( " p " ) . c l a s s e s ( ) = = [ " c l a s s - a " , " c l a s s - b " ]
5 . 7
INTERACTION WITH CONTENT
click()
isDisplayed()
withConfirm{}
withAlert{}
$ ( " a . b t n " ) . c l i c k ( )
$ ( " d i v " ) . i s D i s p l a y e d ( )
w i t h C o n f i r m {
$ ( " b u t t o n . d e l e t e " ) . c l i c k ( )
}
5 . 85 . 9
SENDING INPUT
i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s
/ / S h o r t h a n d f o r s e n d K e y s ( ) m e t h o d o f W e b D r i v e r .
$ ( " d i v " ) < < " a b c "
$ ( " i n p u t " , n a m e : " f o o " ) < < K e y s . c h o r d ( K e y s . C O N T R O L , " c " )
5 . 10
INTERACTION
Using ActionsAPI from WebDriver is possible.
But Geb provides the interactclosure
5 . 11
CONTROL-CLICKING
i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s
i n t e r a c t {
k e y D o w n K e y s . C T R L
c l i c k $ ( " a . m y L i n k " )
k e y U p K e y s . C T R L
}
SIMULATE DRAG-N-DROP
i n t e r a c t {
c l i c k A n d H o l d ( $ ( ' # d r a g g a b l e ' ) )
m o v e B y O f f s e t ( 1 5 0 , 2 0 0 )
r e l e a s e ( )
}
Or easier
i n t e r a c t {
d r a g A n d D r o p B y ( $ ( " # d r a g g a b l e " ) , 1 5 0 , 2 0 0 )
}
5 . 12
MORE INTERACTION WITH FORMS
< f o r m >
< i n p u t t y p e = " t e x t " n a m e = " g e b " v a l u e = " F u n c t i o n a l " / >
< / f o r m >
The value can be read and written via property notation…
$ ( " f o r m " ) . g e b = = " F u n c t i o n a l "
$ ( " f o r m " ) . g e b = " T e s t i n g "
These are literally shortcuts for…
$ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( ) = = " F u n c t i o n a l "
$ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( " T e s t i n g " )
5 . 13
VARIABLES AVAILABLE
title
browser
currentUrl
currentWindow
5 . 14
MORE POSSIBILITIES
Uploading files
Downloading files
Interacting with javascript
js object (Example later)
5 . 156 . 1
STANDALONE GEB SCRIPT
GEB STANDALONE EXAMPLE
Lets try to automate:
Searching for Greach Conference
Click the first link
Hopefully end up on the right homepage
6 . 2
GEB STANDALONE EXAMPLE
g o " h t t p : / / d u c k d u c k g o . c o m "
$ ( ' i n p u t ' , n a m e : ' q ' ) . v a l u e ( " G r e a c h C o n f e r e n c e " )
$ ( ' i n p u t ' , n a m e : ' q ' ) < < K e y s . E N T E R
w a i t F o r ( 1 0 , 1 ) { $ ( " # l i n k s " ) . d i s p l a y e d }
s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s
$ ( " h 2 . r e s u l t _ _ t i t l e " ) . f i r s t ( ) . c l i c k ( )
w a i t F o r { t i t l e . s t a r t s W i t h " G r e a c h " }
6 . 37 . 1
STRUCTURING GEB TESTS
SCENARIO
Lets test a small todo application
Lets test the following
1. Goto list of todos
2. Create new item
3. Delete item again
7 . 27 . 3
GEB SPEC BASICS
i m p o r t g e b . s p o c k . G e b S p e c
@ S t e p w i s e / / E n s u r e s t h e t e s t s a r e r u n s e q u e n t i a l l y
c l a s s T o d o S p e c e x t e n d s G e b S p e c {
/ / S p o c k s p e c s h e r e
}
GEB SPEC (1)
The naive inmaintainable way!
d e f " G o t o i n d e x p a g e " ( ) {
w h e n : ' G o t o i n d e x u r l '
g o ' / '
t h e n : ' V e r i f y w e a r e t h e r e '
t i t l e = = " T o d o L i s t "
}
7 . 4
GEB SPEC (2)
The naive inmaintainable way!
d e f " C r e a t e n e w t o d o " ( ) {
w h e n : ' I n p u t t e x t a n d s u b m i t '
$ ( " # n e w - t o d o " ) < < " D o t h i s "
$ ( " # c r e a t e - b t n " ) . c l i c k ( )
t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t '
w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 4 ' }
$ ( ' l i . t o d o - i t e m ' ) . a n y { i t . t e x t ( ) . c o n t a i n s ' D o t h i s ' }
a n d : ' V e r i f y i n p u t f i e l d e m p t y '
! $ ( " # n e w - t o d o " ) . t e x t ( )
}
7 . 5
GEB SPEC (3)
The naive inmaintainable way!
d e f " D e l e t e t o d o i t e m " ( ) {
w h e n : ' C l i c k d e l e t e a n d a c c e p t '
w i t h C o n f i r m {
$ ( ' b u t t o n ' , 4 ) . c l i c k ( )
}
t h e n : ' V e r i f y i t e m d e l e t e d '
w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 3 ' }
$ ( ' l i . t o d o - i t e m ' ) . e v e r y { ! ( i t . t e x t ( ) . c o n t a i n s ( ' D o t h i s ' ) ) }
}
7 . 68 . 1
GEB SPEC - THE BETTER WAY
If we make a few scenarios, there will be
Much duplication
Many places to correct if we change the layout / DOM
8 . 28 . 3
SOLUTION
Use pages and modules
PAGE OBJECTS
Describes a web page
Url
How to check if we are at the correct place
Content we wish to interact with
.. and how it is found
Helper methods
8 . 4
PAGE OBJECTS
p a c k a g e n e t . g r y d e s k e . g r e a c h . p a g e s
i m p o r t g e b . P a g e
c l a s s A b o u t P a g e e x t e n d s P a g e {
s t a t i c u r l = " / a b o u t "
s t a t i c a t = {
t i t l e = = " A b o u t "
}
s t a t i c c o n t e n t = {
h e a d e r { $ ( ' h 1 ' , 0 ) }
}
}
8 . 58 . 6
CONTENT CLOSURE
s t a t i c c o n t e n t = {
i n f o ( r e q u i r e d : f a l s e ) { $ ( " d i v . i n f o " ) }
m e s s a g e ( w a i t : f a l s e ) { $ ( " d i v . m e s s a g e " ) }
}
8 . 7
MODULES
Describes repeated content
Across pages
Repeated content within the same page
MODULES ACROSS PAGES
p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s
i m p o r t g e b . M o d u l e
c l a s s M e n u b a r M o d u l e e x t e n d s M o d u l e {
s t a t i c b a s e = { $ ( " n a v . n a v b a r " ) }
s t a t i c c o n t e n t = {
h o m e { $ ( ' a ' , t e x t : ' T o d o L i s t ' ) }
a b o u t { $ ( ' a ' , t e x t : ' A b o u t ' ) }
}
}
8 . 8
MODULES FOR REPEATED CONTENT
p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s
i m p o r t g e b . M o d u l e
c l a s s T o d o I t e m M o d u l e e x t e n d s M o d u l e {
s t a t i c c o n t e n t = {
c h e c k b o x { $ ( ' i n p u t ' , t y p e : ' c h e c k b o x ' ) }
l a b e l { $ ( ' l a b e l ' ) . t e x t ( ) }
d e l e t e B t n { $ ( ' b u t t o n ' ) }
}
}
8 . 98 . 10
USING MODULES
s t a t i c c o n t e n t = {
m e n u b a r { m o d u l e M e n u b a r M o d u l e }
t o d o s ( r e q u i r e d : f a l s e ) {
$ ( ' l i . t o d o - i t e m ' ) . m o d u l e L i s t ( T o d o I t e m M o d u l e )
}
}
8 . 11
GEB SPEC - STRUCTURED
Lets try to restructure the ugly spec from before
8 . 12
GEB SPEC - STRUCTURED (1)
d e f " G o t o i n d e x p a g e " ( ) {
w h e n : ' G o t o i n d e x u r l '
t o I n d e x P a g e
t h e n : ' V e r i f y 3 i t e m s p r e s e n t '
a t I n d e x P a g e
c o u n t V a l u e = = ' 3 '
}
GEB SPEC - STRUCTURED (2)
d e f " C r e a t e n e w t o d o " ( ) {
w h e n : ' I n p u t t e x t a n d s u b m i t '
t o d o I n p u t = " D o t h i s "
t o d o S u b m i t . c l i c k ( )
t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t '
w a i t F o r { c o u n t V a l u e = = ' 4 ' }
t o d o s . a n y { i t . l a b e l = = ' D o t h i s ' }
a n d : ' V e r i f y i n p u t f i e l d e m p t y '
! t o d o I n p u t . t e x t ( )
}
8 . 13
GEB SPEC - STRUCTURED (3)
d e f " D e l e t e t o d o i t e m " ( ) {
w h e n : ' C l i c k d e l e t e a n d a c c e p t '
w i t h C o n f i r m {
t o d o s . f i n d { i t . l a b e l = = ' D o t h i s ' } . d e l e t e B t n . c l i c k ( )
}
t h e n : ' V e r i f y i t e m d e l e t e d '
w a i t F o r { c o u n t V a l u e = = ' 3 ' }
t o d o s . e v e r y { i t . l a b e l ! = ' D o t h i s ' }
}
8 . 14
STANDALONE REVISITED
c l a s s D u c k D u c k G o P a g e e x t e n d s g e b . P a g e {
s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m "
s t a t i c a t = { t i t l e = = ~ / D u c k D u c k G o / }
s t a t i c c o n t e n t = {
i n p u t F i e l d { $ ( ' i n p u t ' , n a m e : ' q ' ) }
}
d e f s u b m i t ( ) {
i n p u t F i e l d < < K e y s . E N T E R
}
}
8 . 15
STANDALONE REVISITED
c l a s s D u c k D u c k G o R e s u l t P a g e e x t e n d s g e b . P a g e {
s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m "
s t a t i c a t = { $ ( " # l i n k s " ) . d i s p l a y e d }
s t a t i c c o n t e n t = {
l i n k s { $ ( " h 2 . r e s u l t _ _ t i t l e " ) }
}
d e f c l i c k L i n k ( i n t l i n k N u m b e r ) {
l i n k s [ l i n k N u m b e r ] . c l i c k ( )
}
}
8 . 168 . 17
STANDALONE REVISITED
c l a s s G r e a c h P a g e e x t e n d s g e b . P a g e {
s t a t i c a t = { t i t l e . s t a r t s W i t h ( " G r e a c h " ) }
}
STANDALONE REVISITED
b r o w s e r . w i t h {
t o D u c k D u c k G o P a g e
i n p u t F i e l d < < " G r e a c h C o n f e r e n c e "
s u b m i t ( )
w a i t F o r ( 1 0 , 0 . 5 ) {
a t D u c k D u c k G o R e s u l t P a g e
}
s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s
c l i c k L i n k ( 0 )
w a i t F o r {
a t G r e a c h P a g e
}
}
8 . 189 . 1
GEB WITH RATPACK AND GRAILS
GEB WITH RATPACK
d e p e n d e n c i e s {
. . .
/ / I f u s i n g S p o c k , n e e d t o d e p e n d o n g e b - s p o c k
t e s t C o m p i l e " o r g . g e b i s h : g e b - s p o c k : 0 . 1 3 . 1 "
t e s t C o m p i l e " o r g . s p o c k f r a m e w o r k : s p o c k - c o r e : 1 . 0 - g r o o v y - 2 . 4 "
/ / N e e d a d r i v e r i m p l e m e n t a t i o n
t e s t C o m p i l e (
" o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 "
)
t e s t R u n t i m e (
" o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 "
)
}
9 . 29 . 3
GEB WITH RATPACK
@ S h a r e d
d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( )
d e f s e t u p ( ) {
U R I b a s e = a u t . a d d r e s s
b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( )
}
9 . 4
INTERACTING WITH RATPACK
APPLICATION
When some functionality is needed that is not exposed
through the browser, it can be necessary to interact with the
application under test.
9 . 5
INTERACTING WITH RATPACK
Include in build.gradle
d e p e n d e n c i e s {
. . .
c o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e " )
t e s t C o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e - t e s t " )
. . .
INTERACTING WITH RATPACK
@ S h a r e d
d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( )
R e m o t e C o n t r o l r e m o t e C o n t r o l
d e f s e t u p ( ) {
U R I b a s e = a u t . a d d r e s s
b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( )
r e m o t e C o n t r o l = n e w R e m o t e C o n t r o l ( a u t )
}
9 . 6
INTERACTING WITH RATPACK
d e f " C o m p l e t e i t e m a n d c h e c k d a t a b a s e " ( ) {
w h e n : ' C h e c k i t e m d o n e '
t o d o s . f i n d { i t . l a b e l = = ' G i v e G e b p r e s e n t a t i o n ' }
. c h e c k b o x . c l i c k ( )
t h e n : ' U s e r e m o t e c o n t r o l t o c h e c k d a t a b a s e '
r e m o t e C o n t r o l . e x e c {
B o o l e a n c o m p l e t e d
T o d o I t e m . w i t h N e w S e s s i o n {
T o d o I t e m t o d o I t e m = T o d o I t e m
. f i n d B y T e x t ( ' G i v e G e b p r e s e n t a t i o n ' )
c o m p l e t e d = t o d o I t e m . c o m p l e t e d
}
c o m p l e t e d
} = = t r u e
}
9 . 7
GEB AND GRAILS 2.X
Must install plugin in BuildConfig.groovy
d e p e n d e n c i e s {
. . .
t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 " )
t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 " )
t e s t " o r g . g e b i s h : g e b - s p o c k : 0 . 1 2 . 1 "
}
p l u g i n s {
. . .
t e s t " o r g . g r a i l s . p l u g i n s : g e b : 0 . 1 2 . 1 "
}
9 . 89 . 9
GEB TESTS IN GRAILS 2.X
Tests placed in test/functionalfolder
Running the tests
g r a i l s t e s t - a p p f u n c t i o n a l :
GEB AND GRAILS 3
Geb is default in build.gradle
d e p e n d e n c i e s {
. . .
t e s t C o m p i l e " o r g . g r a i l s . p l u g i n s : g e b "
t e s t R u n t i m e (
" o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - h t m l u n i t - d r i v e r : 2 . 4 7 . 1 "
)
t e s t R u n t i m e " n e t . s o u r c e f o r g e . h t m l u n i t : h t m l u n i t : 2 . 1 8 "
}
9 . 10
GEB TESTS IN GRAILS 3
Creating Geb Spec
g r a i l s c r e a t e - f u n c t i o n a l - t e s t M y G e b S c e n a r i o
Placing the test in src/integration-test/groovy
Running the tests
g r a i l s t e s t - a p p - i n t e g r a t i o n
9 . 11
GENERATED CLASS
@ I n t e g r a t i o n
@ R o l l b a c k
c l a s s D e m o S p e c e x t e n d s G e b S p e c {
v o i d " t e s t s o m e t h i n g " ( ) {
w h e n : " T h e h o m e p a g e i s v i s i t e d "
g o ' / '
t h e n : " T h e t i t l e i s c o r r e c t "
$ ( ' t i t l e ' ) . t e x t ( ) = = " W e l c o m e t o G r a i l s "
}
}
9 . 12
INTERACTING WITH GRAILS 2.5
Tests not running in same JVM
Done with remote-control plugin
Send a closure for execution in application
c o m p i l e " : r e m o t e - c o n t r o l : 2 . 0 "
9 . 139 . 14
INTERACTING WITH GRAILS 3.0
Application is in same jvm
Interaction is possible directly
Tests run as integration tests
9 . 15
INTERACTING WITH GRAILS 3.0
s e t u p :
A t t e n d e e . w i t h N e w T r a n s a c t i o n {
1 5 . t i m e s {
n e w A t t e n d e e ( n a m e : " N $ i t " , e m a i l : " m $ i t @ t . d k " ) . s a v e ( )
}
}
10 . 1
CONFIGURATION AND BROWSER
SUPPORT
10 . 2
GEBCONFIG
Configuration for Geb is placed in GebConfig.groovy
It must be placed in default package scope
 http://www.gebish.org/manual/current/configuration.html
10 . 3
DRIVER
It is possible to configure the browser used.
SUPPORTED DRIVERS
Firefox
Chrome
InternetExplorer
Safari
HtmlUnit
PhantomJS
10 . 410 . 5
DRIVER
It is possible to configure the browser used.
build.gradle
c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - c h r o m e - d r i v e r : 2 . 4 9 . 0 '
c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 4 9 . 0 '
FIREFOX
GebConfig.groovy
i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x P r o f i l e
i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x D r i v e r
d r i v e r = {
F i r e f o x P r o f i l e p r o f i l e = n e w F i r e f o x P r o f i l e ( )
p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . f o l d e r L i s t " , 2 )
p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . d i r " , " / t m p " )
p r o f i l e . s e t P r e f e r e n c e (
" b r o w s e r . h e l p e r A p p s . n e v e r A s k . s a v e T o D i s k " , " t e x t / c s v " )
d e f d r i v e r I n s t a n c e = n e w F i r e f o x D r i v e r ( p r o f i l e )
d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( ) . m a x i m i z e ( )
d r i v e r I n s t a n c e
}
10 . 610 . 7
CHROME
Needs ChromeDriver downloaded
Pretty fast and stable
CHROME (1)
GebConfig.groovy
p r i v a t e S t r i n g d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) {
S t r i n g o s = S y s t e m . g e t P r o p e r t y ( " o s . n a m e " ) . t o L o w e r C a s e ( ) ;
d e f l o c = " h t t p : / / c h r o m e d r i v e r . s t o r a g e . g o o g l e a p i s . c o m / 2 . 2 0 "
i f ( o s . c o n t a i n s ( ' m a c ' ) ) {
r e t u r n " $ { l o c } / c h r o m e d r i v e r _ m a c 3 2 . z i p "
}
i f ( o s . c o n t a i n s ( ' w i n ' ) ) {
r e t u r n " $ { l o c } / c h r o m e d r i v e r _ w i n 3 2 . z i p "
}
r e t u r n " $ { l o c } / c h r o m e d r i v e r _ l i n u x 6 4 . z i p "
}
10 . 8
CHROME (2)
GebConfig.groovy
p r i v a t e v o i d d o w n l o a d D r i v e r ( F i l e f i l e , S t r i n g p a t h ) {
i f ( ! f i l e . e x i s t s ( ) ) {
d e f a n t = n e w A n t B u i l d e r ( )
a n t . g e t ( s r c : p a t h , d e s t : ' d r i v e r . z i p ' )
a n t . u n z i p ( s r c : ' d r i v e r . z i p ' , d e s t : f i l e . p a r e n t )
a n t . d e l e t e ( f i l e : ' d r i v e r . z i p ' )
a n t . c h m o d ( f i l e : f i l e , p e r m : ' 7 0 0 ' )
}
}
10 . 9
CHROME (3)
GebConfig.groovy
d e f c h r o m e D r i v e r = n e w F i l e ( ' b u i l d / d r i v e r s / c h r o m e / c h r o m e d r i v e r ' )
d o w n l o a d D r i v e r ( c h r o m e D r i v e r ,
d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) )
S y s t e m . s e t P r o p e r t y ( ' w e b d r i v e r . c h r o m e . d r i v e r ' ,
c h r o m e D r i v e r . a b s o l u t e P a t h )
d r i v e r = {
d e f d r i v e r I n s t a n c e = n e w C h r o m e D r i v e r ( )
d e f b r o w s e r W i n d o w = d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( )
/ / w i d t h , h e i g h t
b r o w s e r W i n d o w . s i z e = n e w D i m e n s i o n ( 1 0 0 0 , 2 5 0 0 )
b r o w s e r W i n d o w . p o s i t i o n = n e w P o i n t ( 0 , 0 )
d r i v e r I n s t a n c e
}
10 . 1010 . 11
CLOUD BASED TESTING
SauceLabs
BrowserStack
SAUCELABS
GebConfig.groovy
i m p o r t g e b . d r i v e r . S a u c e L a b s D r i v e r F a c t o r y
d e f s l B r o w s e r = S y s t e m . g e t P r o p e r t y ( " g e b . s a u c e l a b s . b r o w s e r " )
i f ( s l B r o w s e r ) {
d r i v e r = {
d e f u s e r n a m e = S y s t e m . g e t e n v (
" G E B _ S A U C E _ L A B S _ U S E R " )
a s s e r t u s e r n a m e
d e f a c c e s s K e y = S y s t e m . g e t e n v (
" G E B _ S A U C E _ L A B S _ A C C E S S _ P A S S W O R D " )
a s s e r t a c c e s s K e y
n e w S a u c e L a b s D r i v e r F a c t o r y ( ) . c r e a t e (
s a u c e L a b s B r o w s e r , u s e r n a m e , a c c e s s K e y )
}
}
10 . 12
SAUCELABS
build.gradle
a p p l y p l u g i n : " g e b - s a u c e l a b s "
r e p o s i t o r i e s {
. . .
m a v e n C e n t r a l ( )
}
d e p e n d e n c i e s {
. . .
s a u c e C o n n e c t " c o m . s a u c e l a b s : c i - s a u c e : 1 . 1 1 3 "
}
10 . 13
SAUCELABS
s a u c e L a b s {
b r o w s e r s {
f i r e f o x _ l i n u x _ 1 9
d e l e g a t e . " i n t e r n e t e x p l o r e r _ v i s t a _ 9 "
n e x u s 4 {
c a p a b i l i t i e s (
b r o w s e r N a m e : " a n d r o i d " , p l a t f o r m : " L i n u x " ,
v e r s i o n : " 4 . 4 " , d e v i c e N a m e : " L G N e x u s 4 "
)
} }
t a s k {
t e s t C l a s s e s D i r = t e s t . t e s t C l a s s e s D i r
t e s t S r c D i r s = t e s t . t e s t S r c D i r s
c l a s s p a t h = t e s t . c l a s s p a t h
}
a c c o u n t {
u s e r n a m e = " u s e r n a m e "
a c c e s s K e y = " a p i - k e y "
}
c o n n e c t {
/ / p o r t = 4 4 4 4
/ / a d d i t i o n a l O p t i o n s = [ ' - - p r o x y ' , ' p r o x y . e x a m p l e . c o m : 8 0 8 0 ' ]
} }
10 . 1411 . 1
JAVASCRIPT
In case you need to interact using javascript
11 . 2
EXECUTING JAVASCRIPT
Clicking a button that is hidden will create a
ElementNotVisibleException
< f i e l d s e t c l a s s = " w e l l " s t y l e = " d i s p l a y : n o n e " >
< a h r e f = " / l i s t " c l a s s = " b t n " > L i s t < / a >
< / f i e l d s e t >
11 . 3
EXECUTING JAVASCRIPT
J a v a s c r i p t E x e c u t o r e x e c u t o r = ( J a v a s c r i p t E x e c u t o r ) d r i v e r
e x e c u t o r . e x e c u t e S c r i p t ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
11 . 4
WRAPPING JAVASCRIPT
d e f j s ( S t r i n g s c r i p t ) {
( d r i v e r a s J a v a s c r i p t E x e c u t o r ) . e x e c u t e S c r i p t ( s c r i p t )
}
j s ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
11 . 5
JQUERY SHORTHAND
$ ( " d i v # a " ) . j q u e r y . m o u s e o v e r ( )
$ ( " # a " ) . j q u e r y . t r i g g e r ( ' m o u s e o v e r ' )
12 . 1
WAITING AND PAUSING
WAITING
GebConfig.groovy
w a i t i n g {
t i m e o u t = 1 0
r e t r y I n t e r v a l = 0 . 5
}
b a s e N a v i g a t o r W a i t i n g = t r u e
a t C h e c k W a i t i n g = t r u e
12 . 2
USING WAITING
< d i v c l a s s = " f a d e - m e - i n " s t y l e = " d i s p l a y : n o n e " >
H i - a r e y o w a i t i n g f o r m e ?
< / d i v >
< s c r i p t >
$ ( ' d i v . f a d e - m e - i n ' ) . d e l a y ( 3 0 0 0 ) . s l i d e D o w n ( ) ;
< / s c r i p t >
s t a t i c c o n t e n t = {
f a d e I n M e s s a g e { $ ( ' d i v . f a d e - m e - i n ' ) }
}
t h e n :
w a i t F o r {
f a d e I n M e s s a g e . t e x t ( ) = = ' H i - a r e y o w a i t i n g f o r m e ? '
}
12 . 3
PAUSING GEB
p r i v a t e v o i d p a u s e ( ) {
j s . e x e c " " " ( f u n c t i o n ( ) {
w i n d o w . _ _ g e b P a u s e d = t r u e ;
v a r d i v = d o c u m e n t . c r e a t e E l e m e n t ( " d i v " ) ;
d i v . s e t A t t r i b u t e ( ' s t y l e ' ,
" p o s i t i o n : a b s o l u t e ; t o p : 0 p x ; r i g h t : 0 p x ; z - i n d e x : 3 0 0 0 ;  
p a d d i n g : 1 0 p x ; b a c k g r o u n d - c o l o r : r e d ; " ) ;
v a r b u t t o n = d o c u m e n t . c r e a t e E l e m e n t ( " b u t t o n " ) ;
b u t t o n . i n n e r H T M L = " U n p a u s e G e b " ;
b u t t o n . o n c l i c k = f u n c t i o n ( ) {
w i n d o w . _ _ g e b P a u s e d = f a l s e ;
}
d i v . a p p e n d C h i l d ( b u t t o n ) ;
d o c u m e n t . g e t E l e m e n t s B y T a g N a m e ( " b o d y " ) [ 0 ] . a p p e n d C h i l d ( d i v ) ;
} ) ( ) ; " " "
w a i t F o r ( 3 0 0 ) { ! j s . _ _ g e b P a u s e d }
}
12 . 412 . 5
PAUSING GEB
w h e n : ' D e m o i n g p a u s e '
p a u s e ( ) / / P a u s e G e b u n t i l b u t t o n p r e s s e d
PAUSING GEB
12 . 613 . 1
REPORTING
13 . 2
TEST REPORTS
Nicely formatted
Spock power-assert format
13 . 3
SPOCK REPORTS
Take a look at pluginSpock Reports
t e s t C o m p i l e ( ' c o m . a t h a y d e s : s p o c k - r e p o r t s : 1 . 2 . 1 0 ' ) {
/ / t h i s a v o i d s a f f e c t i n g y o u r v e r s i o n o f G r o o v y / S p o c k
t r a n s i t i v e = f a l s e
}
SPOCK REPORTS
SPOCK REPORTS
13 . 4
SCREENSHOTS
Screenshots and HTML from end of each test:
Extend from GebReportingSpec
c l a s s A t t e n d e e F u n c t i o n a l S p e c e x t e n d s G e b R e p o r t i n g S p e c
GebConfig.groovy
r e p o r t s D i r = n e w F i l e ( " b u i l d / g e b - r e p o r t s " )
r e p o r t O n T e s t F a i l u r e O n l y = t r u e
13 . 513 . 613 . 7
AD-HOC SCREENSHOTS
r e p o r t " W h e n - f o r m - i s - j u s t - f i l l e d "
Saves a report in reportsDir
Numbered in increasing order
14
OTHER USAGES
Screenscraping of a site
Solving complex problems like 2048
RESOURCES
http://gebish.org
https://groups.google.com/forum/#!forum/geb-user
https://github.com/geb
https://gist.github.com/melix/9619800
https://github.com/tomaslin/grails-test-recipes
https://fbflex.wordpress.com/2010/08/25/geb-and-grails-
tips-tricks-and-gotchas/
https://github.com/JacobAae/gr8conf-in-2016-geb-for-
grails
1516
QUESTIONS?
some text...

More Related Content

What's hot

GitGot: The Swiss Army Chainsaw of Git Repo Management
GitGot: The Swiss Army Chainsaw of Git Repo ManagementGitGot: The Swiss Army Chainsaw of Git Repo Management
GitGot: The Swiss Army Chainsaw of Git Repo ManagementJohn Anderson
 
Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)Patricia Aas
 
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경Mintak Son
 
Challenging Your Assumptions
Challenging Your AssumptionsChallenging Your Assumptions
Challenging Your AssumptionsKristina Fox
 
C++ The Principles of Most Surprise
C++ The Principles of Most SurpriseC++ The Principles of Most Surprise
C++ The Principles of Most SurprisePatricia Aas
 
第7回 ECMA-262 Edition5.1読書会
第7回 ECMA-262 Edition5.1読書会第7回 ECMA-262 Edition5.1読書会
第7回 ECMA-262 Edition5.1読書会Shou Takenaka
 
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Alberto De Ávila Hernández
 
Software Vulnerabilities in C and C++ (CppCon 2018)
Software Vulnerabilities in C and C++ (CppCon 2018)Software Vulnerabilities in C and C++ (CppCon 2018)
Software Vulnerabilities in C and C++ (CppCon 2018)Patricia Aas
 
Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Patricia Aas
 
톰캣 #05+a-배치-parallel deployment
톰캣 #05+a-배치-parallel deployment톰캣 #05+a-배치-parallel deployment
톰캣 #05+a-배치-parallel deploymentGyuSeok Lee
 
Reading Other Peoples Code (NDC Sydney 2018)
Reading Other Peoples Code (NDC Sydney 2018)Reading Other Peoples Code (NDC Sydney 2018)
Reading Other Peoples Code (NDC Sydney 2018)Patricia Aas
 
Monitoring using Sensu
Monitoring using SensuMonitoring using Sensu
Monitoring using Sensuripienaar
 
Effective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiDEffective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiDCODEiD PHP Community
 
Geb for Testing Your Grails Application GR8Conf India 2016
Geb for Testing Your Grails Application  GR8Conf India 2016Geb for Testing Your Grails Application  GR8Conf India 2016
Geb for Testing Your Grails Application GR8Conf India 2016Jacob Aae Mikkelsen
 
Testing Java Microservices Devoxx be 2017
Testing Java Microservices Devoxx be 2017Testing Java Microservices Devoxx be 2017
Testing Java Microservices Devoxx be 2017Alex Soto
 
The Anatomy of an Exploit (CPPP 2019)
The Anatomy of an Exploit (CPPP 2019)The Anatomy of an Exploit (CPPP 2019)
The Anatomy of an Exploit (CPPP 2019)Patricia Aas
 
Thoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguageThoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguagePatricia Aas
 
The Anatomy of an Exploit (NDC TechTown 2019)
The Anatomy of an Exploit (NDC TechTown 2019)The Anatomy of an Exploit (NDC TechTown 2019)
The Anatomy of an Exploit (NDC TechTown 2019)Patricia Aas
 

What's hot (20)

GitGot: The Swiss Army Chainsaw of Git Repo Management
GitGot: The Swiss Army Chainsaw of Git Repo ManagementGitGot: The Swiss Army Chainsaw of Git Repo Management
GitGot: The Swiss Army Chainsaw of Git Repo Management
 
Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)
 
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
 
Challenging Your Assumptions
Challenging Your AssumptionsChallenging Your Assumptions
Challenging Your Assumptions
 
C++ The Principles of Most Surprise
C++ The Principles of Most SurpriseC++ The Principles of Most Surprise
C++ The Principles of Most Surprise
 
第7回 ECMA-262 Edition5.1読書会
第7回 ECMA-262 Edition5.1読書会第7回 ECMA-262 Edition5.1読書会
第7回 ECMA-262 Edition5.1読書会
 
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
 
Software Vulnerabilities in C and C++ (CppCon 2018)
Software Vulnerabilities in C and C++ (CppCon 2018)Software Vulnerabilities in C and C++ (CppCon 2018)
Software Vulnerabilities in C and C++ (CppCon 2018)
 
Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)
 
톰캣 #05+a-배치-parallel deployment
톰캣 #05+a-배치-parallel deployment톰캣 #05+a-배치-parallel deployment
톰캣 #05+a-배치-parallel deployment
 
Reading Other Peoples Code (NDC Sydney 2018)
Reading Other Peoples Code (NDC Sydney 2018)Reading Other Peoples Code (NDC Sydney 2018)
Reading Other Peoples Code (NDC Sydney 2018)
 
Monitoring using Sensu
Monitoring using SensuMonitoring using Sensu
Monitoring using Sensu
 
Effective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiDEffective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiD
 
Geb for Testing Your Grails Application GR8Conf India 2016
Geb for Testing Your Grails Application  GR8Conf India 2016Geb for Testing Your Grails Application  GR8Conf India 2016
Geb for Testing Your Grails Application GR8Conf India 2016
 
Tools Bringing Happiness
Tools Bringing HappinessTools Bringing Happiness
Tools Bringing Happiness
 
Testing Java Microservices Devoxx be 2017
Testing Java Microservices Devoxx be 2017Testing Java Microservices Devoxx be 2017
Testing Java Microservices Devoxx be 2017
 
The Anatomy of an Exploit (CPPP 2019)
The Anatomy of an Exploit (CPPP 2019)The Anatomy of an Exploit (CPPP 2019)
The Anatomy of an Exploit (CPPP 2019)
 
Thoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguageThoughts On Learning A New Programming Language
Thoughts On Learning A New Programming Language
 
The Anatomy of an Exploit (NDC TechTown 2019)
The Anatomy of an Exploit (NDC TechTown 2019)The Anatomy of an Exploit (NDC TechTown 2019)
The Anatomy of an Exploit (NDC TechTown 2019)
 
Yes, you can git!
Yes, you can git!Yes, you can git!
Yes, you can git!
 

Viewers also liked

From Grails to Android: A Simple Journey
From Grails to Android: A Simple JourneyFrom Grails to Android: A Simple Journey
From Grails to Android: A Simple JourneyAnnyce Davis
 
Geb for testing your grails application
Geb for testing your grails applicationGeb for testing your grails application
Geb for testing your grails applicationJacobAae
 
Creating ASTTs The painful truth
Creating ASTTs The painful truthCreating ASTTs The painful truth
Creating ASTTs The painful truthMario García
 
Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016Alvaro Sanchez-Mariscal
 
Reactive Streams and the Wide World of Groovy
Reactive Streams and the Wide World of GroovyReactive Streams and the Wide World of Groovy
Reactive Streams and the Wide World of GroovySteve Pember
 

Viewers also liked (9)

From Grails to Android: A Simple Journey
From Grails to Android: A Simple JourneyFrom Grails to Android: A Simple Journey
From Grails to Android: A Simple Journey
 
Geb for testing your grails application
Geb for testing your grails applicationGeb for testing your grails application
Geb for testing your grails application
 
Spock and Geb in Action
Spock and Geb in ActionSpock and Geb in Action
Spock and Geb in Action
 
Creating ASTTs The painful truth
Creating ASTTs The painful truthCreating ASTTs The painful truth
Creating ASTTs The painful truth
 
Greach 2016 dockerize your grails
Greach 2016   dockerize your grailsGreach 2016   dockerize your grails
Greach 2016 dockerize your grails
 
Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016
 
Reactive Streams and the Wide World of Groovy
Reactive Streams and the Wide World of GroovyReactive Streams and the Wide World of Groovy
Reactive Streams and the Wide World of Groovy
 
Grooscript and Grails 3
Grooscript and Grails 3Grooscript and Grails 3
Grooscript and Grails 3
 
Geb with spock
Geb with spockGeb with spock
Geb with spock
 

Similar to Geb for browser automation

PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!Blanca Mancilla
 
GraphQL Relay Introduction
GraphQL Relay IntroductionGraphQL Relay Introduction
GraphQL Relay IntroductionChen-Tsu Lin
 
Social Network Analysis With R
Social Network Analysis With RSocial Network Analysis With R
Social Network Analysis With RDavid Chiu
 
Spring scala - Sneaking Scala into your corporation
Spring scala  - Sneaking Scala into your corporationSpring scala  - Sneaking Scala into your corporation
Spring scala - Sneaking Scala into your corporationHenryk Konsek
 
Top 10 php classic traps
Top 10 php classic trapsTop 10 php classic traps
Top 10 php classic trapsDamien Seguy
 
PostgreSQL Day italy 2016 Unit Test
PostgreSQL Day italy 2016 Unit TestPostgreSQL Day italy 2016 Unit Test
PostgreSQL Day italy 2016 Unit TestAndrea Adami
 
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar PradhanAwesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar PradhanAjeet Singh Raina
 
The Backside of the Class (CSS Day 2015)
The Backside of the Class (CSS Day 2015)The Backside of the Class (CSS Day 2015)
The Backside of the Class (CSS Day 2015)Stephen Hay
 
Using Phing for Fun and Profit
Using Phing for Fun and ProfitUsing Phing for Fun and Profit
Using Phing for Fun and ProfitNicholas Jansma
 
Automated tests - facts and myths
Automated tests - facts and mythsAutomated tests - facts and myths
Automated tests - facts and mythsWojciech Sznapka
 
Top 10 php classic traps DPC 2020
Top 10 php classic traps DPC 2020Top 10 php classic traps DPC 2020
Top 10 php classic traps DPC 2020Damien Seguy
 
Top 10 php classic traps confoo
Top 10 php classic traps confooTop 10 php classic traps confoo
Top 10 php classic traps confooDamien Seguy
 
Modeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the worldModeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the worldCédric Brun
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2ady36
 
Modeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ frModeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ frCédric Brun
 
No Flex Zone: Empathy Driven Development
No Flex Zone: Empathy Driven DevelopmentNo Flex Zone: Empathy Driven Development
No Flex Zone: Empathy Driven DevelopmentDuretti H.
 
Continuous delivery with Gradle
Continuous delivery with GradleContinuous delivery with Gradle
Continuous delivery with GradleBob Paulin
 
Tong Hop Bai Tap C
Tong Hop Bai Tap CTong Hop Bai Tap C
Tong Hop Bai Tap CSamQuiDaiBo
 

Similar to Geb for browser automation (20)

PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!
 
GraphQL Relay Introduction
GraphQL Relay IntroductionGraphQL Relay Introduction
GraphQL Relay Introduction
 
Social Network Analysis With R
Social Network Analysis With RSocial Network Analysis With R
Social Network Analysis With R
 
Spring scala - Sneaking Scala into your corporation
Spring scala  - Sneaking Scala into your corporationSpring scala  - Sneaking Scala into your corporation
Spring scala - Sneaking Scala into your corporation
 
Top 10 php classic traps
Top 10 php classic trapsTop 10 php classic traps
Top 10 php classic traps
 
PostgreSQL Day italy 2016 Unit Test
PostgreSQL Day italy 2016 Unit TestPostgreSQL Day italy 2016 Unit Test
PostgreSQL Day italy 2016 Unit Test
 
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar PradhanAwesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
 
The Backside of the Class (CSS Day 2015)
The Backside of the Class (CSS Day 2015)The Backside of the Class (CSS Day 2015)
The Backside of the Class (CSS Day 2015)
 
Using Phing for Fun and Profit
Using Phing for Fun and ProfitUsing Phing for Fun and Profit
Using Phing for Fun and Profit
 
Automated tests - facts and myths
Automated tests - facts and mythsAutomated tests - facts and myths
Automated tests - facts and myths
 
Top 10 php classic traps DPC 2020
Top 10 php classic traps DPC 2020Top 10 php classic traps DPC 2020
Top 10 php classic traps DPC 2020
 
Top 10 php classic traps confoo
Top 10 php classic traps confooTop 10 php classic traps confoo
Top 10 php classic traps confoo
 
Modeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the worldModeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the world
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
 
PHP Tips & Tricks
PHP Tips & TricksPHP Tips & Tricks
PHP Tips & Tricks
 
Modeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ frModeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ fr
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
 
No Flex Zone: Empathy Driven Development
No Flex Zone: Empathy Driven DevelopmentNo Flex Zone: Empathy Driven Development
No Flex Zone: Empathy Driven Development
 
Continuous delivery with Gradle
Continuous delivery with GradleContinuous delivery with Gradle
Continuous delivery with Gradle
 
Tong Hop Bai Tap C
Tong Hop Bai Tap CTong Hop Bai Tap C
Tong Hop Bai Tap C
 

Recently uploaded

Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...
Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...
Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...ICT Watch - Indonesia
 
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)ICT Watch - Indonesia
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxAndrieCagasanAkio
 
Cybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best PracticesCybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best PracticesLumiverse Solutions Pvt Ltd
 
How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...rrouter90
 
Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxmibuzondetrabajo
 
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...vmzoxnx5
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119APNIC
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxMario
 

Recently uploaded (9)

Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...
Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...
Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...
 
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptx
 
Cybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best PracticesCybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best Practices
 
How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...
 
Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptx
 
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptx
 

Geb for browser automation

  • 2. AGENDA Functional testing Geb - cudos and history How Geb works Geb and Ratpack, Grails 2 and 3 Browser support Tips and Tricks
  • 3. 2 . 1 JACOB AAE MIKKELSEN Senior 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 Southern Denmark @JacobAae Blogs The Grails Diary
  • 4. 2 . 23 . 1 FUNCTIONAL TESTING
  • 5.
  • 8. 3 . 4 FUNCTIONAL TESTING Ignores the specifics of the underlying so ware component under test. Whitebox / Greybox Merely asserts that providing certain input results in certain output. Web-application: Programmatically controlling a web browser to simulate the actions of a user on a web page.
  • 9. 3 . 5 BROWSER AUTOMATION
  • 10. 3 . 64 . 1
  • 11. 4 . 2 GEB HISTORY Started in November 2009 Created by Luke Daley Current project lead Marcin Erdman
  • 12. GEB IMPLEMENTATION Build on top of the WebDriver browser automation library successor to the Selenium Remote Control (RC) testing framework. Selenium RC → JavaScript to interact WebDriver → native browser drivers Use JUnit or Spock
  • 13. 4 . 3 WEBDRIVER Very active development Stable API and feature set Verbose Low level Not a complete solution
  • 14. 4 . 4 WHY GEB jQuery 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
  • 15. 4 . 5
  • 16. 5 . 1 USING GEB
  • 17. 4 . 6 5 . 2 NAVIGATOR The $()method returns a Navigator object General format - Jquery like selecter syntax $ ( < c s s s e l e c t o r > , < i n d e x / r a n g e > , < a t t r i b u t e / t e x t m a t c h e r s > )
  • 18. GEB SELECTORS (1) / / m a t c h a l l ' p ' e l e m e n t s o n p a g e $ ( " p " ) / / m a t c h t h e f i r s t ' p ' e l e m e n t o n t h e p a g e $ ( " p " , 0 ) / / A l l ' d i v ' e l e m e n t s w i t h a t i t l e v a l u e ' s e c t i o n ' $ ( " d i v " , t i t l e : " s e c t i o n " ) / / m a t c h t h e f i r s t ' d i v ' e l e m e n t t e x t ' s e c t i o n ' $ ( " d i v " , 0 , t e x t : " s e c t i o n " ) / / m a t c h t h e f i r s t ' d i v ' e l e m e n t w i t h t h e c l a s s ' m a i n ' $ ( " d i v . m a i n " , 0 )
  • 19. 5 . 3 GEB SELECTORS (2) Text attribute supports regex / / A n y d i v w i t h t h e t e x t s t a r t i n g w i h G R 8 $ ( " d i v " , t e x t : ~ / G R 8 . + / ) $ ( " p " , t e x t : s t a r t s W i t h ( " G R 8 " ) ) / / A n d o t h e r h a n d y p r e d i c a t e s $ ( " d i v " , c l a s s : c o n t a i n s ( " u i - " ) )
  • 20. 5 . 4 GEB SELECTORS (3) Selecting returns Navigatorobjects / / T h e p a r e n t o f t h e f i r s t d i v $ ( " d i v " , 0 ) . p a r e n t ( ) / / A l l t a b l e s w i t h a c e l l s p a c i n g / / a t t r i b u t e v a l u e o f 0 t h a t a r e n e s t e d i n a p a r a g r a p h $ ( " p " ) . f i n d ( " t a b l e " , c e l l s p a c i n g : ' 0 ' )
  • 21. 5 . 55 . 6 CSS SUPPORT $ ( " t a b l e t r : n t h - c h i l d ( 2 n + 1 ) t d " )
  • 22. RETRIVING INFORMATION < p i d = " s a m p l e " c l a s s = " c l a s s - a c l a s s - b " t i t l e = " S a m p l e p e l e m e n t " > S a m p l e t e x t < / p > $ ( " p " ) . t e x t ( ) = = " S a m p l e t e x t " $ ( " # s a m p l e " ) . t a g ( ) = = " p " $ ( " p " ) . @ t i t l e = = " S a m p l e p e l e m e n t " $ ( " p " ) . c l a s s e s ( ) = = [ " c l a s s - a " , " c l a s s - b " ]
  • 23. 5 . 7 INTERACTION WITH CONTENT click() isDisplayed() withConfirm{} withAlert{} $ ( " a . b t n " ) . c l i c k ( ) $ ( " d i v " ) . i s D i s p l a y e d ( ) w i t h C o n f i r m { $ ( " b u t t o n . d e l e t e " ) . c l i c k ( ) }
  • 24. 5 . 85 . 9 SENDING INPUT i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s / / S h o r t h a n d f o r s e n d K e y s ( ) m e t h o d o f W e b D r i v e r . $ ( " d i v " ) < < " a b c " $ ( " i n p u t " , n a m e : " f o o " ) < < K e y s . c h o r d ( K e y s . C O N T R O L , " c " )
  • 25. 5 . 10 INTERACTION Using ActionsAPI from WebDriver is possible. But Geb provides the interactclosure
  • 26. 5 . 11 CONTROL-CLICKING i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s i n t e r a c t { k e y D o w n K e y s . C T R L c l i c k $ ( " a . m y L i n k " ) k e y U p K e y s . C T R L }
  • 27. SIMULATE DRAG-N-DROP i n t e r a c t { c l i c k A n d H o l d ( $ ( ' # d r a g g a b l e ' ) ) m o v e B y O f f s e t ( 1 5 0 , 2 0 0 ) r e l e a s e ( ) } Or easier i n t e r a c t { d r a g A n d D r o p B y ( $ ( " # d r a g g a b l e " ) , 1 5 0 , 2 0 0 ) }
  • 28. 5 . 12 MORE INTERACTION WITH FORMS < f o r m > < i n p u t t y p e = " t e x t " n a m e = " g e b " v a l u e = " F u n c t i o n a l " / > < / f o r m > The value can be read and written via property notation… $ ( " f o r m " ) . g e b = = " F u n c t i o n a l " $ ( " f o r m " ) . g e b = " T e s t i n g " These are literally shortcuts for… $ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( ) = = " F u n c t i o n a l " $ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( " T e s t i n g " )
  • 29. 5 . 13 VARIABLES AVAILABLE title browser currentUrl currentWindow
  • 30. 5 . 14 MORE POSSIBILITIES Uploading files Downloading files Interacting with javascript js object (Example later)
  • 31. 5 . 156 . 1 STANDALONE GEB SCRIPT
  • 32. GEB STANDALONE EXAMPLE Lets try to automate: Searching for Greach Conference Click the first link Hopefully end up on the right homepage
  • 33. 6 . 2 GEB STANDALONE EXAMPLE g o " h t t p : / / d u c k d u c k g o . c o m " $ ( ' i n p u t ' , n a m e : ' q ' ) . v a l u e ( " G r e a c h C o n f e r e n c e " ) $ ( ' i n p u t ' , n a m e : ' q ' ) < < K e y s . E N T E R w a i t F o r ( 1 0 , 1 ) { $ ( " # l i n k s " ) . d i s p l a y e d } s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s $ ( " h 2 . r e s u l t _ _ t i t l e " ) . f i r s t ( ) . c l i c k ( ) w a i t F o r { t i t l e . s t a r t s W i t h " G r e a c h " }
  • 34. 6 . 37 . 1 STRUCTURING GEB TESTS
  • 35. SCENARIO Lets test a small todo application Lets test the following 1. Goto list of todos 2. Create new item 3. Delete item again
  • 36. 7 . 27 . 3 GEB SPEC BASICS i m p o r t g e b . s p o c k . G e b S p e c @ S t e p w i s e / / E n s u r e s t h e t e s t s a r e r u n s e q u e n t i a l l y c l a s s T o d o S p e c e x t e n d s G e b S p e c { / / S p o c k s p e c s h e r e }
  • 37. GEB SPEC (1) The naive inmaintainable way! d e f " G o t o i n d e x p a g e " ( ) { w h e n : ' G o t o i n d e x u r l ' g o ' / ' t h e n : ' V e r i f y w e a r e t h e r e ' t i t l e = = " T o d o L i s t " }
  • 38. 7 . 4 GEB SPEC (2) The naive inmaintainable way! d e f " C r e a t e n e w t o d o " ( ) { w h e n : ' I n p u t t e x t a n d s u b m i t ' $ ( " # n e w - t o d o " ) < < " D o t h i s " $ ( " # c r e a t e - b t n " ) . c l i c k ( ) t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t ' w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 4 ' } $ ( ' l i . t o d o - i t e m ' ) . a n y { i t . t e x t ( ) . c o n t a i n s ' D o t h i s ' } a n d : ' V e r i f y i n p u t f i e l d e m p t y ' ! $ ( " # n e w - t o d o " ) . t e x t ( ) }
  • 39. 7 . 5 GEB SPEC (3) The naive inmaintainable way! d e f " D e l e t e t o d o i t e m " ( ) { w h e n : ' C l i c k d e l e t e a n d a c c e p t ' w i t h C o n f i r m { $ ( ' b u t t o n ' , 4 ) . c l i c k ( ) } t h e n : ' V e r i f y i t e m d e l e t e d ' w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 3 ' } $ ( ' l i . t o d o - i t e m ' ) . e v e r y { ! ( i t . t e x t ( ) . c o n t a i n s ( ' D o t h i s ' ) ) } }
  • 40. 7 . 68 . 1 GEB SPEC - THE BETTER WAY If we make a few scenarios, there will be Much duplication Many places to correct if we change the layout / DOM
  • 41.
  • 42. 8 . 28 . 3 SOLUTION Use pages and modules
  • 43. PAGE OBJECTS Describes a web page Url How to check if we are at the correct place Content we wish to interact with .. and how it is found Helper methods
  • 44. 8 . 4 PAGE OBJECTS p a c k a g e n e t . g r y d e s k e . g r e a c h . p a g e s i m p o r t g e b . P a g e c l a s s A b o u t P a g e e x t e n d s P a g e { s t a t i c u r l = " / a b o u t " s t a t i c a t = { t i t l e = = " A b o u t " } s t a t i c c o n t e n t = { h e a d e r { $ ( ' h 1 ' , 0 ) } } }
  • 45. 8 . 58 . 6 CONTENT CLOSURE s t a t i c c o n t e n t = { i n f o ( r e q u i r e d : f a l s e ) { $ ( " d i v . i n f o " ) } m e s s a g e ( w a i t : f a l s e ) { $ ( " d i v . m e s s a g e " ) } }
  • 46. 8 . 7 MODULES Describes repeated content Across pages Repeated content within the same page
  • 47. MODULES ACROSS PAGES p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s i m p o r t g e b . M o d u l e c l a s s M e n u b a r M o d u l e e x t e n d s M o d u l e { s t a t i c b a s e = { $ ( " n a v . n a v b a r " ) } s t a t i c c o n t e n t = { h o m e { $ ( ' a ' , t e x t : ' T o d o L i s t ' ) } a b o u t { $ ( ' a ' , t e x t : ' A b o u t ' ) } } }
  • 48. 8 . 8 MODULES FOR REPEATED CONTENT p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s i m p o r t g e b . M o d u l e c l a s s T o d o I t e m M o d u l e e x t e n d s M o d u l e { s t a t i c c o n t e n t = { c h e c k b o x { $ ( ' i n p u t ' , t y p e : ' c h e c k b o x ' ) } l a b e l { $ ( ' l a b e l ' ) . t e x t ( ) } d e l e t e B t n { $ ( ' b u t t o n ' ) } } }
  • 49. 8 . 98 . 10 USING MODULES s t a t i c c o n t e n t = { m e n u b a r { m o d u l e M e n u b a r M o d u l e } t o d o s ( r e q u i r e d : f a l s e ) { $ ( ' l i . t o d o - i t e m ' ) . m o d u l e L i s t ( T o d o I t e m M o d u l e ) } }
  • 50. 8 . 11 GEB SPEC - STRUCTURED Lets try to restructure the ugly spec from before
  • 51. 8 . 12 GEB SPEC - STRUCTURED (1) d e f " G o t o i n d e x p a g e " ( ) { w h e n : ' G o t o i n d e x u r l ' t o I n d e x P a g e t h e n : ' V e r i f y 3 i t e m s p r e s e n t ' a t I n d e x P a g e c o u n t V a l u e = = ' 3 ' }
  • 52. GEB SPEC - STRUCTURED (2) d e f " C r e a t e n e w t o d o " ( ) { w h e n : ' I n p u t t e x t a n d s u b m i t ' t o d o I n p u t = " D o t h i s " t o d o S u b m i t . c l i c k ( ) t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t ' w a i t F o r { c o u n t V a l u e = = ' 4 ' } t o d o s . a n y { i t . l a b e l = = ' D o t h i s ' } a n d : ' V e r i f y i n p u t f i e l d e m p t y ' ! t o d o I n p u t . t e x t ( ) }
  • 53. 8 . 13 GEB SPEC - STRUCTURED (3) d e f " D e l e t e t o d o i t e m " ( ) { w h e n : ' C l i c k d e l e t e a n d a c c e p t ' w i t h C o n f i r m { t o d o s . f i n d { i t . l a b e l = = ' D o t h i s ' } . d e l e t e B t n . c l i c k ( ) } t h e n : ' V e r i f y i t e m d e l e t e d ' w a i t F o r { c o u n t V a l u e = = ' 3 ' } t o d o s . e v e r y { i t . l a b e l ! = ' D o t h i s ' } }
  • 54. 8 . 14 STANDALONE REVISITED c l a s s D u c k D u c k G o P a g e e x t e n d s g e b . P a g e { s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m " s t a t i c a t = { t i t l e = = ~ / D u c k D u c k G o / } s t a t i c c o n t e n t = { i n p u t F i e l d { $ ( ' i n p u t ' , n a m e : ' q ' ) } } d e f s u b m i t ( ) { i n p u t F i e l d < < K e y s . E N T E R } }
  • 55. 8 . 15 STANDALONE REVISITED c l a s s D u c k D u c k G o R e s u l t P a g e e x t e n d s g e b . P a g e { s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m " s t a t i c a t = { $ ( " # l i n k s " ) . d i s p l a y e d } s t a t i c c o n t e n t = { l i n k s { $ ( " h 2 . r e s u l t _ _ t i t l e " ) } } d e f c l i c k L i n k ( i n t l i n k N u m b e r ) { l i n k s [ l i n k N u m b e r ] . c l i c k ( ) } }
  • 56. 8 . 168 . 17 STANDALONE REVISITED c l a s s G r e a c h P a g e e x t e n d s g e b . P a g e { s t a t i c a t = { t i t l e . s t a r t s W i t h ( " G r e a c h " ) } }
  • 57. STANDALONE REVISITED b r o w s e r . w i t h { t o D u c k D u c k G o P a g e i n p u t F i e l d < < " G r e a c h C o n f e r e n c e " s u b m i t ( ) w a i t F o r ( 1 0 , 0 . 5 ) { a t D u c k D u c k G o R e s u l t P a g e } s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s c l i c k L i n k ( 0 ) w a i t F o r { a t G r e a c h P a g e } }
  • 58. 8 . 189 . 1 GEB WITH RATPACK AND GRAILS
  • 59. GEB WITH RATPACK d e p e n d e n c i e s { . . . / / I f u s i n g S p o c k , n e e d t o d e p e n d o n g e b - s p o c k t e s t C o m p i l e " o r g . g e b i s h : g e b - s p o c k : 0 . 1 3 . 1 " t e s t C o m p i l e " o r g . s p o c k f r a m e w o r k : s p o c k - c o r e : 1 . 0 - g r o o v y - 2 . 4 " / / N e e d a d r i v e r i m p l e m e n t a t i o n t e s t C o m p i l e ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 " ) t e s t R u n t i m e ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 " ) }
  • 60. 9 . 29 . 3 GEB WITH RATPACK @ S h a r e d d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( ) d e f s e t u p ( ) { U R I b a s e = a u t . a d d r e s s b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( ) }
  • 61. 9 . 4 INTERACTING WITH RATPACK APPLICATION When some functionality is needed that is not exposed through the browser, it can be necessary to interact with the application under test.
  • 62. 9 . 5 INTERACTING WITH RATPACK Include in build.gradle d e p e n d e n c i e s { . . . c o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e " ) t e s t C o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e - t e s t " ) . . .
  • 63. INTERACTING WITH RATPACK @ S h a r e d d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( ) R e m o t e C o n t r o l r e m o t e C o n t r o l d e f s e t u p ( ) { U R I b a s e = a u t . a d d r e s s b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( ) r e m o t e C o n t r o l = n e w R e m o t e C o n t r o l ( a u t ) }
  • 64. 9 . 6 INTERACTING WITH RATPACK d e f " C o m p l e t e i t e m a n d c h e c k d a t a b a s e " ( ) { w h e n : ' C h e c k i t e m d o n e ' t o d o s . f i n d { i t . l a b e l = = ' G i v e G e b p r e s e n t a t i o n ' } . c h e c k b o x . c l i c k ( ) t h e n : ' U s e r e m o t e c o n t r o l t o c h e c k d a t a b a s e ' r e m o t e C o n t r o l . e x e c { B o o l e a n c o m p l e t e d T o d o I t e m . w i t h N e w S e s s i o n { T o d o I t e m t o d o I t e m = T o d o I t e m . f i n d B y T e x t ( ' G i v e G e b p r e s e n t a t i o n ' ) c o m p l e t e d = t o d o I t e m . c o m p l e t e d } c o m p l e t e d } = = t r u e }
  • 65. 9 . 7 GEB AND GRAILS 2.X Must install plugin in BuildConfig.groovy d e p e n d e n c i e s { . . . t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 " ) t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 " ) t e s t " o r g . g e b i s h : g e b - s p o c k : 0 . 1 2 . 1 " } p l u g i n s { . . . t e s t " o r g . g r a i l s . p l u g i n s : g e b : 0 . 1 2 . 1 " }
  • 66. 9 . 89 . 9 GEB TESTS IN GRAILS 2.X Tests placed in test/functionalfolder Running the tests g r a i l s t e s t - a p p f u n c t i o n a l :
  • 67. GEB AND GRAILS 3 Geb is default in build.gradle d e p e n d e n c i e s { . . . t e s t C o m p i l e " o r g . g r a i l s . p l u g i n s : g e b " t e s t R u n t i m e ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - h t m l u n i t - d r i v e r : 2 . 4 7 . 1 " ) t e s t R u n t i m e " n e t . s o u r c e f o r g e . h t m l u n i t : h t m l u n i t : 2 . 1 8 " }
  • 68. 9 . 10 GEB TESTS IN GRAILS 3 Creating Geb Spec g r a i l s c r e a t e - f u n c t i o n a l - t e s t M y G e b S c e n a r i o Placing the test in src/integration-test/groovy Running the tests g r a i l s t e s t - a p p - i n t e g r a t i o n
  • 69. 9 . 11 GENERATED CLASS @ I n t e g r a t i o n @ R o l l b a c k c l a s s D e m o S p e c e x t e n d s G e b S p e c { v o i d " t e s t s o m e t h i n g " ( ) { w h e n : " T h e h o m e p a g e i s v i s i t e d " g o ' / ' t h e n : " T h e t i t l e i s c o r r e c t " $ ( ' t i t l e ' ) . t e x t ( ) = = " W e l c o m e t o G r a i l s " } }
  • 70. 9 . 12 INTERACTING WITH GRAILS 2.5 Tests not running in same JVM Done with remote-control plugin Send a closure for execution in application c o m p i l e " : r e m o t e - c o n t r o l : 2 . 0 "
  • 71. 9 . 139 . 14 INTERACTING WITH GRAILS 3.0 Application is in same jvm Interaction is possible directly Tests run as integration tests
  • 72. 9 . 15 INTERACTING WITH GRAILS 3.0 s e t u p : A t t e n d e e . w i t h N e w T r a n s a c t i o n { 1 5 . t i m e s { n e w A t t e n d e e ( n a m e : " N $ i t " , e m a i l : " m $ i t @ t . d k " ) . s a v e ( ) } }
  • 73. 10 . 1 CONFIGURATION AND BROWSER SUPPORT
  • 74. 10 . 2 GEBCONFIG Configuration for Geb is placed in GebConfig.groovy It must be placed in default package scope  http://www.gebish.org/manual/current/configuration.html
  • 75. 10 . 3 DRIVER It is possible to configure the browser used.
  • 77. 10 . 410 . 5 DRIVER It is possible to configure the browser used. build.gradle c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - c h r o m e - d r i v e r : 2 . 4 9 . 0 ' c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 4 9 . 0 '
  • 78. FIREFOX GebConfig.groovy i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x P r o f i l e i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x D r i v e r d r i v e r = { F i r e f o x P r o f i l e p r o f i l e = n e w F i r e f o x P r o f i l e ( ) p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . f o l d e r L i s t " , 2 ) p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . d i r " , " / t m p " ) p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . h e l p e r A p p s . n e v e r A s k . s a v e T o D i s k " , " t e x t / c s v " ) d e f d r i v e r I n s t a n c e = n e w F i r e f o x D r i v e r ( p r o f i l e ) d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( ) . m a x i m i z e ( ) d r i v e r I n s t a n c e }
  • 79. 10 . 610 . 7 CHROME Needs ChromeDriver downloaded Pretty fast and stable
  • 80. CHROME (1) GebConfig.groovy p r i v a t e S t r i n g d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) { S t r i n g o s = S y s t e m . g e t P r o p e r t y ( " o s . n a m e " ) . t o L o w e r C a s e ( ) ; d e f l o c = " h t t p : / / c h r o m e d r i v e r . s t o r a g e . g o o g l e a p i s . c o m / 2 . 2 0 " i f ( o s . c o n t a i n s ( ' m a c ' ) ) { r e t u r n " $ { l o c } / c h r o m e d r i v e r _ m a c 3 2 . z i p " } i f ( o s . c o n t a i n s ( ' w i n ' ) ) { r e t u r n " $ { l o c } / c h r o m e d r i v e r _ w i n 3 2 . z i p " } r e t u r n " $ { l o c } / c h r o m e d r i v e r _ l i n u x 6 4 . z i p " }
  • 81. 10 . 8 CHROME (2) GebConfig.groovy p r i v a t e v o i d d o w n l o a d D r i v e r ( F i l e f i l e , S t r i n g p a t h ) { i f ( ! f i l e . e x i s t s ( ) ) { d e f a n t = n e w A n t B u i l d e r ( ) a n t . g e t ( s r c : p a t h , d e s t : ' d r i v e r . z i p ' ) a n t . u n z i p ( s r c : ' d r i v e r . z i p ' , d e s t : f i l e . p a r e n t ) a n t . d e l e t e ( f i l e : ' d r i v e r . z i p ' ) a n t . c h m o d ( f i l e : f i l e , p e r m : ' 7 0 0 ' ) } }
  • 82. 10 . 9 CHROME (3) GebConfig.groovy d e f c h r o m e D r i v e r = n e w F i l e ( ' b u i l d / d r i v e r s / c h r o m e / c h r o m e d r i v e r ' ) d o w n l o a d D r i v e r ( c h r o m e D r i v e r , d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) ) S y s t e m . s e t P r o p e r t y ( ' w e b d r i v e r . c h r o m e . d r i v e r ' , c h r o m e D r i v e r . a b s o l u t e P a t h ) d r i v e r = { d e f d r i v e r I n s t a n c e = n e w C h r o m e D r i v e r ( ) d e f b r o w s e r W i n d o w = d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( ) / / w i d t h , h e i g h t b r o w s e r W i n d o w . s i z e = n e w D i m e n s i o n ( 1 0 0 0 , 2 5 0 0 ) b r o w s e r W i n d o w . p o s i t i o n = n e w P o i n t ( 0 , 0 ) d r i v e r I n s t a n c e }
  • 83. 10 . 1010 . 11 CLOUD BASED TESTING SauceLabs BrowserStack
  • 84. SAUCELABS GebConfig.groovy i m p o r t g e b . d r i v e r . S a u c e L a b s D r i v e r F a c t o r y d e f s l B r o w s e r = S y s t e m . g e t P r o p e r t y ( " g e b . s a u c e l a b s . b r o w s e r " ) i f ( s l B r o w s e r ) { d r i v e r = { d e f u s e r n a m e = S y s t e m . g e t e n v ( " G E B _ S A U C E _ L A B S _ U S E R " ) a s s e r t u s e r n a m e d e f a c c e s s K e y = S y s t e m . g e t e n v ( " G E B _ S A U C E _ L A B S _ A C C E S S _ P A S S W O R D " ) a s s e r t a c c e s s K e y n e w S a u c e L a b s D r i v e r F a c t o r y ( ) . c r e a t e ( s a u c e L a b s B r o w s e r , u s e r n a m e , a c c e s s K e y ) } }
  • 85. 10 . 12 SAUCELABS build.gradle a p p l y p l u g i n : " g e b - s a u c e l a b s " r e p o s i t o r i e s { . . . m a v e n C e n t r a l ( ) } d e p e n d e n c i e s { . . . s a u c e C o n n e c t " c o m . s a u c e l a b s : c i - s a u c e : 1 . 1 1 3 " }
  • 86. 10 . 13 SAUCELABS s a u c e L a b s { b r o w s e r s { f i r e f o x _ l i n u x _ 1 9 d e l e g a t e . " i n t e r n e t e x p l o r e r _ v i s t a _ 9 " n e x u s 4 { c a p a b i l i t i e s ( b r o w s e r N a m e : " a n d r o i d " , p l a t f o r m : " L i n u x " , v e r s i o n : " 4 . 4 " , d e v i c e N a m e : " L G N e x u s 4 " ) } } t a s k { t e s t C l a s s e s D i r = t e s t . t e s t C l a s s e s D i r t e s t S r c D i r s = t e s t . t e s t S r c D i r s c l a s s p a t h = t e s t . c l a s s p a t h } a c c o u n t { u s e r n a m e = " u s e r n a m e " a c c e s s K e y = " a p i - k e y " } c o n n e c t { / / p o r t = 4 4 4 4 / / a d d i t i o n a l O p t i o n s = [ ' - - p r o x y ' , ' p r o x y . e x a m p l e . c o m : 8 0 8 0 ' ] } }
  • 87. 10 . 1411 . 1 JAVASCRIPT In case you need to interact using javascript
  • 88. 11 . 2 EXECUTING JAVASCRIPT Clicking a button that is hidden will create a ElementNotVisibleException < f i e l d s e t c l a s s = " w e l l " s t y l e = " d i s p l a y : n o n e " > < a h r e f = " / l i s t " c l a s s = " b t n " > L i s t < / a > < / f i e l d s e t >
  • 89. 11 . 3 EXECUTING JAVASCRIPT J a v a s c r i p t E x e c u t o r e x e c u t o r = ( J a v a s c r i p t E x e c u t o r ) d r i v e r e x e c u t o r . e x e c u t e S c r i p t ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
  • 90. 11 . 4 WRAPPING JAVASCRIPT d e f j s ( S t r i n g s c r i p t ) { ( d r i v e r a s J a v a s c r i p t E x e c u t o r ) . e x e c u t e S c r i p t ( s c r i p t ) } j s ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
  • 91. 11 . 5 JQUERY SHORTHAND $ ( " d i v # a " ) . j q u e r y . m o u s e o v e r ( ) $ ( " # a " ) . j q u e r y . t r i g g e r ( ' m o u s e o v e r ' )
  • 92. 12 . 1 WAITING AND PAUSING
  • 93. WAITING GebConfig.groovy w a i t i n g { t i m e o u t = 1 0 r e t r y I n t e r v a l = 0 . 5 } b a s e N a v i g a t o r W a i t i n g = t r u e a t C h e c k W a i t i n g = t r u e
  • 94. 12 . 2 USING WAITING < d i v c l a s s = " f a d e - m e - i n " s t y l e = " d i s p l a y : n o n e " > H i - a r e y o w a i t i n g f o r m e ? < / d i v > < s c r i p t > $ ( ' d i v . f a d e - m e - i n ' ) . d e l a y ( 3 0 0 0 ) . s l i d e D o w n ( ) ; < / s c r i p t > s t a t i c c o n t e n t = { f a d e I n M e s s a g e { $ ( ' d i v . f a d e - m e - i n ' ) } } t h e n : w a i t F o r { f a d e I n M e s s a g e . t e x t ( ) = = ' H i - a r e y o w a i t i n g f o r m e ? ' }
  • 95. 12 . 3 PAUSING GEB p r i v a t e v o i d p a u s e ( ) { j s . e x e c " " " ( f u n c t i o n ( ) { w i n d o w . _ _ g e b P a u s e d = t r u e ; v a r d i v = d o c u m e n t . c r e a t e E l e m e n t ( " d i v " ) ; d i v . s e t A t t r i b u t e ( ' s t y l e ' , " p o s i t i o n : a b s o l u t e ; t o p : 0 p x ; r i g h t : 0 p x ; z - i n d e x : 3 0 0 0 ; p a d d i n g : 1 0 p x ; b a c k g r o u n d - c o l o r : r e d ; " ) ; v a r b u t t o n = d o c u m e n t . c r e a t e E l e m e n t ( " b u t t o n " ) ; b u t t o n . i n n e r H T M L = " U n p a u s e G e b " ; b u t t o n . o n c l i c k = f u n c t i o n ( ) { w i n d o w . _ _ g e b P a u s e d = f a l s e ; } d i v . a p p e n d C h i l d ( b u t t o n ) ; d o c u m e n t . g e t E l e m e n t s B y T a g N a m e ( " b o d y " ) [ 0 ] . a p p e n d C h i l d ( d i v ) ; } ) ( ) ; " " " w a i t F o r ( 3 0 0 ) { ! j s . _ _ g e b P a u s e d } }
  • 96. 12 . 412 . 5 PAUSING GEB w h e n : ' D e m o i n g p a u s e ' p a u s e ( ) / / P a u s e G e b u n t i l b u t t o n p r e s s e d
  • 98. 12 . 613 . 1 REPORTING
  • 99. 13 . 2 TEST REPORTS Nicely formatted Spock power-assert format
  • 100. 13 . 3 SPOCK REPORTS Take a look at pluginSpock Reports t e s t C o m p i l e ( ' c o m . a t h a y d e s : s p o c k - r e p o r t s : 1 . 2 . 1 0 ' ) { / / t h i s a v o i d s a f f e c t i n g y o u r v e r s i o n o f G r o o v y / S p o c k t r a n s i t i v e = f a l s e }
  • 103. 13 . 4 SCREENSHOTS Screenshots and HTML from end of each test: Extend from GebReportingSpec c l a s s A t t e n d e e F u n c t i o n a l S p e c e x t e n d s G e b R e p o r t i n g S p e c GebConfig.groovy r e p o r t s D i r = n e w F i l e ( " b u i l d / g e b - r e p o r t s " ) r e p o r t O n T e s t F a i l u r e O n l y = t r u e
  • 104. 13 . 513 . 613 . 7 AD-HOC SCREENSHOTS r e p o r t " W h e n - f o r m - i s - j u s t - f i l l e d " Saves a report in reportsDir Numbered in increasing order
  • 105. 14 OTHER USAGES Screenscraping of a site Solving complex problems like 2048