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

Effective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiDEffective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiD
CODEiD PHP Community
Ā 

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

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

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
Henryk Konsek
Ā 
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
CĆ©dric Brun
Ā 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
ady36
Ā 
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
CĆ©dric Brun
Ā 
Continuous delivery with Gradle
Continuous delivery with GradleContinuous delivery with Gradle
Continuous delivery with Gradle
Bob Paulin
Ā 
Tong Hop Bai Tap C
Tong Hop Bai Tap CTong Hop Bai Tap C
Tong Hop Bai Tap C
SamQuiDaiBo
Ā 

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

Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Call Girls In Delhi Whatsup 9873940964 Enjoy Unlimited Pleasure
Ā 
Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
soniya singh
Ā 
@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶
@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶
@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶
Call Girls In Delhi Whatsup 9873940964 Enjoy Unlimited Pleasure
Ā 
Delhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip CallDelhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip Call
shivangimorya083
Ā 
Lucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRL
Lucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRLLucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRL
Lucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRL
imonikaupta
Ā 
Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
soniya singh
Ā 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
sexy call girls service in goa
Ā 
Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...
SofiyaSharma5
Ā 

Recently uploaded (20)

Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Ā 
š“€¤Call On 7877925207 š“€¤ Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
š“€¤Call On 7877925207 š“€¤ Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...š“€¤Call On 7877925207 š“€¤ Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
š“€¤Call On 7877925207 š“€¤ Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
Ā 
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebGDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
Ā 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
Ā 
Russian Call Girls in %(+971524965298 )# Call Girls in Dubai
Russian Call Girls in %(+971524965298  )#  Call Girls in DubaiRussian Call Girls in %(+971524965298  )#  Call Girls in Dubai
Russian Call Girls in %(+971524965298 )# Call Girls in Dubai
Ā 
INDIVIDUAL ASSIGNMENT #3 CBG, PRESENTATION.
INDIVIDUAL ASSIGNMENT #3 CBG, PRESENTATION.INDIVIDUAL ASSIGNMENT #3 CBG, PRESENTATION.
INDIVIDUAL ASSIGNMENT #3 CBG, PRESENTATION.
Ā 
Enjoy Nightāš”Call Girls Dlf City Phase 3 Gurgaon >ą¼’8448380779 Escort Service
Enjoy Nightāš”Call Girls Dlf City Phase 3 Gurgaon >ą¼’8448380779 Escort ServiceEnjoy Nightāš”Call Girls Dlf City Phase 3 Gurgaon >ą¼’8448380779 Escort Service
Enjoy Nightāš”Call Girls Dlf City Phase 3 Gurgaon >ą¼’8448380779 Escort Service
Ā 
Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Defence Colony Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Ā 
Call Now ā˜Ž 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.
Call Now ā˜Ž 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.Call Now ā˜Ž 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.
Call Now ā˜Ž 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.
Ā 
@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶
@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶
@9999965857 šŸ«¦ Sexy Desi Call Girls Laxmi Nagar šŸ’“ High Profile Escorts Delhi šŸ«¶
Ā 
Delhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip CallDelhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ā˜Žāœ”šŸ‘Œāœ” Whatsapp Hard And Sexy Vip Call
Ā 
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call GirlVIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
Ā 
Nanded City ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready ...
Nanded City ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready ...Nanded City ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready ...
Nanded City ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready ...
Ā 
Hireā† Young Call Girls in Tilak nagar (Delhi) ā˜Žļø 9205541914 ā˜Žļø Independent Esc...
Hireā† Young Call Girls in Tilak nagar (Delhi) ā˜Žļø 9205541914 ā˜Žļø Independent Esc...Hireā† Young Call Girls in Tilak nagar (Delhi) ā˜Žļø 9205541914 ā˜Žļø Independent Esc...
Hireā† Young Call Girls in Tilak nagar (Delhi) ā˜Žļø 9205541914 ā˜Žļø Independent Esc...
Ā 
Lucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRL
Lucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRLLucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRL
Lucknow ā¤CALL GIRL 88759*99948 ā¤CALL GIRLS IN Lucknow ESCORT SERVICEā¤CALL GIRL
Ā 
Call Now ā˜Ž 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Call Now ā˜Ž 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.Call Now ā˜Ž 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Call Now ā˜Ž 8264348440 !! Call Girls in Shahpur Jat Escort Service Delhi N.C.R.
Ā 
Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Call Girls In Pratap Nagar Delhi šŸ’ÆCall Us šŸ”8264348440šŸ”
Ā 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Ā 
On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024
Ā 
Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...
Low Rate Young Call Girls in Sector 63 Mamura Noida āœ”ļøā˜†9289244007āœ”ļøā˜† Female E...
Ā 

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